C ++中初始化列表的顺序

Order of Initializer list in C++

我了解对于非静态成员变量,初始化列表中的求值顺序是根据 class 中声明的顺序。

考虑以下来自 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 的构造函数需要 Y 的引用,我们最好先初始化 y_;这意味着 y_ 必须在 x_ 之前声明。

我预计上面的程序会出现段错误,但下面是我的 o/p。有人可以解释一下吗?

-bash-4.1$ ./a.out
Using Y
0x7fffffffe0c1
Initializing Y
0x7fffffffe0c1

I expected above program to give seg fault but below is my o/p.

理论上您的代码会受到未定义行为的影响。

Space 已为对象分配但尚未初始化。此类对象和指向此类对象的指针可以以有限的方式使用,但在此类对象上调用非静态成员函数会导致未定义的行为。

来自https://timsong-cpp.github.io/cppwp/n3337/basic.life#5

The program has undefined behavior if:

(5.1) the object will be or was of a class type with a non-trivial destructor and the pointer is used as the operand of a delete-expression,

(5.2) the pointer is used to access a non-static data member or call a non-static member function of the object, or

您没有看到任何不良行为的最可能原因是 Y 没有任何成员变量。如果将成员变量添加到 Y 并在 Y:f() 中使用它,您很可能会更容易注意到问题。

class Z {
   public:
      Z() throw();
   protected:
      X x_;
      Y y_;
};

Z::Z() throw() : y_(), x_(y_) {}

Z 中,您在 y_ 之前声明了 x_。因此,xy_ 之前构造,而不管您的初始化程序的顺序如何。

并且,在构造 y_ 之前初始化 x_(y_) 会产生未定义的行为。


I expected above program to give seg fault

未定义行为未定义。你不应该有什么特别的期待。