C+中构造函数的初始化顺序+; 通过在C++中实例化一个对象,使用下面的类,我会得到一个分段错误或中止,这取决于声明成员变量的顺序。例如。将mMemberVar和mAnotherMemberVar放在mAnotherCountVar之后会导致segfault。从这个清单中,我从成员变量中删除了std::ofstream,这导致了与位置无关的分段错误

C+中构造函数的初始化顺序+; 通过在C++中实例化一个对象,使用下面的类,我会得到一个分段错误或中止,这取决于声明成员变量的顺序。例如。将mMemberVar和mAnotherMemberVar放在mAnotherCountVar之后会导致segfault。从这个清单中,我从成员变量中删除了std::ofstream,这导致了与位置无关的分段错误,c++,memory,constructor,initialization,C++,Memory,Constructor,Initialization,我认为订单不是直接的问题,但你认为原因是什么?这个类是一个大型项目的一部分,但是这个类中的这个就是第一次出现错误的地方 class COneClass : public IInterface { public: COneClass(); virtual ~COneClass(); static const unsigned int sStaticVar; static const unsigned int sAnotherStaticVar; private: CO

我认为订单不是直接的问题,但你认为原因是什么?这个类是一个大型项目的一部分,但是这个类中的这个就是第一次出现错误的地方

class COneClass : public IInterface
{
public:

  COneClass();

  virtual ~COneClass();

  static const unsigned int sStaticVar;
  static const unsigned int sAnotherStaticVar;


private:
  COneClass();
  COneClass(const COneClass& );
  COneClass& operator=(const COneClass& );

  int mMemberVar;
  int mAnotherMemberVar;
  bool mIsActive;
  bool mBoolMemberVar;
  bool mAnotherBoolMemberVar;
  unsigned int mCountVar;
  unsigned int mAnotherCountVar;
};

COneClass::COneClass() :
  mMemberVar(0),
  mAnotherMemberVar(0),
  mIsActive(false), 
  mBoolMemberVar(false),
  mAnotherBoolMemberVar(false),
  mCountVar(sStaticVar),
  mAnotherCountVar(sAnotherStaticVar)
{
}

我认为整个班级都不是直接的问题。您能通过使用这个类生成一个最小的崩溃代码吗?在我看来,问题出在代码库的其他地方


但是,您可以添加一个
bool Invariant()常量函数调用该类,并使用
assert(Invariant())调用它(仅在调试版本中)
在构造函数末尾以及在进入和退出所有公共函数时。这可能会帮助您“尽早崩溃,经常崩溃”,从而指出一些有问题的代码。

类成员是按声明顺序初始化的。init列表中的顺序并不重要。在您的情况下,顺序如下:
mMemberVar->mAnotherMemberVar->mIsActive->mBoolMemberVar->mAnotherBoolMemberVar->mCountVar->mAnotherCountVar

您发布的代码中没有任何异常之处。要么是
接口中的某个构造函数出现故障,要么是其他完全错误的东西。也许您在某个地方遇到了缓冲区溢出,它正在读取更改结构顺序的数据

也许这是“静态初始化顺序失败”的一种情况,因为使用静态成员初始化mCountVar和mAnotherCountVar


您可以在列表中初始化为零,然后在构造函数体中赋值。

可以根据您拥有公共静态变量和私有构造函数这一事实来判断(说到这一点,您如何能够拥有构造函数的公共和私有定义??)。这些符号表示此处可能存在与其他类的依赖关系。

在包含类自身构造函数的主体之前调用成员的构造函数 被执行。构造函数是按照它们在类中声明的顺序调用的,而不是按照 而不是它们在初始值设定项列表中的显示顺序

为避免混淆,最好按声明顺序指定初始值设定项

成员析构函数按与构造相反的顺序调用,每件事情都能正常工作

class MyClass//**1: mem-init**
{
private:
long number;
bool on;
public:
MyClass(long n, bool ison) : number(n), on(ison) {}
};

MyClass(long n, bool ison) //2 initialization within constructor's body
{
number = n;
on = ison;
}
就MyClass的构造函数而言,这两种形式之间没有实质性的区别。这是由于编译器处理mem初始化列表的方式造成的。编译器扫描mem初始化列表,并在用户编写代码之前将初始化代码插入构造函数的主体。因此,编译器将第一个示例中的构造函数扩展为第二个示例中的构造函数。尽管如此,在以下四种情况下,在使用mem初始化列表和在构造函数主体内部初始化之间进行选择是非常重要的:

  • 常量成员的初始化
  • 参考成员的初始化
  • 将参数传递给基类或嵌入对象的构造函数
  • 成员对象的初始化

这看起来不像您的真实代码。但是要注意,在实际代码中,类成员是按照它们在类中定义的顺序构造的,而与构造函数中初始值设定项列表的顺序无关。如果您提到更改类中成员的顺序会影响问题,那么这可能就是问题所在。例如,您的代码可能会执行以下操作:

class MyClass {
public:
    const int member1;
    const int member2;
    MyClass() {
      : member2(0),
      : member1(member2) // ERROR: this runs first because member1 is defined first
                      // member2 not yet constructed; assigns undefined value to member1
    {}
};

你说“init列表中的顺序不重要”,这似乎不对me@SSS:不,没有错:“基类对象和成员数据对象都是按照声明顺序初始化的,不管构造函数定义中初始化列表的顺序如何。”()@fretje:看来我错了,你是对的,我会做更多的家庭作业,很快会给你回复。谢谢你的评论,否则我会一直这样想that@fretje:mem初始化列表由编译器处理,因此,您无法保证SSS所说的内容得到扩展——原因很简单,但可能不是直观的:当对象被析构函数时,任何成员对象的析构函数都必须按与构造相反的顺序调用。因为可以有2个或更多具有不同初始化列表的构造函数,所以不能使用初始化列表来定义构造顺序,因此只使用固定顺序,即类定义中的声明顺序。(C.F. Scott Meyer,有效C++,项目13。)该示例中存在问题,如它所写的:(1)基类未定义,(2)默认构造函数被声明两次,(3)静态成员没有定义(94.2/4只适用于指定初始化器)。既然您已经介绍了这个示例,为什么不添加一个“main”并编写一个完整的程序来说明问题呢。@Rainer,您应该向我们展示静态变量是如何定义的。这有很大的不同。如果它们是由常量表达式初始化的,那么一切都很好,但如果不是,那么您可能会遇到这些问题。。。