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_
。因此,x
在 y_
之前构造,而不管您的初始化程序的顺序如何。
并且,在构造 y_
之前初始化 x_(y_)
会产生未定义的行为。
I expected above program to give seg fault
未定义行为未定义。你不应该有什么特别的期待。
我了解对于非静态成员变量,初始化列表中的求值顺序是根据 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_
。因此,x
在 y_
之前构造,而不管您的初始化程序的顺序如何。
并且,在构造 y_
之前初始化 x_(y_)
会产生未定义的行为。
I expected above program to give seg fault
未定义行为未定义。你不应该有什么特别的期待。