成员构造函数和析构函数调用的顺序
哦,C++大师,我寻求你的智慧。讲standardese给我,并告诉我,如果C++保证下面的程序:成员构造函数和析构函数调用的顺序
#include <iostream>
using namespace std;
struct A
{
A() { cout << "A::A" << endl; }
~A() { cout << "A::~" << endl; }
};
struct B
{
B() { cout << "B::B" << endl; }
~B() { cout << "B::~" << endl; }
};
struct C
{
C() { cout << "C::C" << endl; }
~C() { cout << "C::~" << endl; }
};
struct Aggregate
{
A a;
B b;
C c;
};
int main()
{
Aggregate a;
return 0;
}
总是会产生
A::A
B::B
C::C
C::~
B::~
A::~
换句话说,被成员保证按声明的顺序进行初始化和反摧毁订购?
换句话说,成员是否保证按照声明的顺序初始化并以相反的顺序销毁?
对两者都是。见12.6.2
初始化应在 下列顺序进行:
首先,并且仅用于 最派生 类的构造如下所述,虚拟基 类应按照 的顺序进行初始化,它们出现在深度优先的 从 的有向无环图的左到右遍历中: 类,其中“从左到右”是 基类 中的名称的顺序 base-specifier-list中派生类中的名称。
然后,直接 基类应在 声明的顺序,因为它们出现在 基符列表(不管 的MEM-初始化的顺序)进行初始化。
然后,非静态数据成员应 初始化中,他们在类定义 声明 顺序(再次不管 MEM-初始化的顺序)。
最后,执行构造函数 的 复合语句。 [注意: 声明命令的授权为 确保基本和成员子对象 以 初始化的相反顺序销毁。末端注]
如果我没有记错的话,对两者都是这样... 把它想象成一个堆栈。先推,最后一搏。因此,在实例化第一个实例时,它会按堆栈顺序存入内存。然后,第二个被推倒,第三个被推倒,等等。然后,当销毁你的实例时,程序将查找第一个要销毁的实例,最后一个被推送。 但我可能是这样解释错误,但这是我在做C/C++和ASM时学到的。 – 2010-02-12 19:03:13
是的,是的。对于成员变量,销毁顺序总是与构造顺序相反。
是的,他们是(非静态成员)。初始化(构造)见12.6.2/5,破坏见12.4/6。
+1,注意这是针对_non-static_成员的。 :-) – 2010-02-12 18:48:50
是,标准的保障对象在创建它们相反的顺序得到破坏。原因是一个对象可能使用另一个对象,因此依赖于它。试想一下:
struct A { };
struct B {
A &a;
B(A& a) : a(a) { }
};
int main() {
A a;
B b(a);
}
如果a
是进行破坏之前b
然后b
将持有无效成员引用。通过以创建它们的相反顺序破坏对象,我们保证正确的破坏。
这是一个相当普遍的原因,当类变得越来越大而且不可思议时,就会产生微妙的错误。当你有50个数据成员,并且在构造器初始化列表中初始化它们时,可以很容易假定构造的顺序是初始化器列表中的顺序。毕竟,代码编写者已经小心地列出了这个列表......不是吗? – Permaquid 2010-02-13 05:06:42