我理解,对于非静态成员变量,初始化列表中的评估顺序是根据类中声明的顺序。
请考虑以下来自isocpp的示例
#include <iostream>
class Y {
public:
Y();
void f();
};
Y::Y() { std::cout << "Initializing Y\n"<<this<<"\n"; }
void Y::f() { std::cout << "Using Y\n"<<this<<"\n"; }
class X {
public:
X(Y& y);
};
X::X(Y& y) { y.f(); }
class Z {
public:
Z() throw();
protected:
X x_;
Y y_;
};
Z::Z() throw() : y_(), x_(y_) {}
int main()
{
Z z;
return 0;
}
由于X的ctor需要Y的参考,我们必须首先初始化y_;这意味着必须在x_之前声明y_。
我期望上面的程序给出seg错误,但下面是我的o / p。有人可以对此有所了解。
-bash-4.1$ ./a.out
Using Y
0x7fffffffe0c1
Initializing Y
0x7fffffffe0c1
class Z { public: Z() throw(); protected: X x_; Y y_; }; Z::Z() throw() : y_(), x_(y_) {}
在Z
,你在x_
之前宣布y_
。因此,无论初始化器的顺序如何,x
都是在y_
之前构建的。
并且,在构造x_(y_)
之前初始化y_
会产生不确定的行为。
我期望上面的程序给出seg错误
未定义的行为未定义。你不应该特别期待任何事情。
我期望上面的程序给出seg错误,但下面是我的o / p。
理论上,您的代码受到未定义的行为的影响。
已为该对象分配空间但尚未初始化。这些对象和指向这些对象的指针可以以有限的方式使用,但是在这样的对象上调用非静态成员函数是导致未定义的行为的原因。
来自https://timsong-cpp.github.io/cppwp/n3337/basic.life#5:
如果出现以下情况,该程
(5.1)对象将是或具有非平凡析构函数的类类型,并且指针用作delete-expression的操作数,
(5.2)指针用于访问非静态数据成员或调用对象的非静态成员函数,或
你没有看到任何不良行为的最可能原因是Y
没有任何成员变量。如果您将成员变量添加到Y
并在Y:f()
中使用它,您很可能会更容易发现问题。