我有以下C ++代码:
#include <iostream>
struct A
{
A() { std::cout << "A" << ++x; }
A(int x) : A() { std::cout << x; }
~A() { std::cout << "D"; }
static int x;
};
int A::x = 0;
struct B
{
A a, aa, aaa;
B() : aa(1), a(2) { std::cout << "B" << std::endl; }
~B() { std::cout << "B" << A::x; }
};
B beta;
int main()
{
return 0;
}
除了析构函数调用之外,我理解控制流中的所有内容。 这是没有析构函数的控制流程:
创建对象B
调用构造函数B. 分别叫a,aa,aaa
2.1 for a,调用A(int x)
2.2 aa,调用A(int x)
2.3 aaa,请致电A()
现在4.步骤是调用析构函数B,我知道。
我不知道的是为A调用析构函数的顺序是什么。 分别是aa,aa,aaa还是aaa,aa,a?
提前致谢。
答案 0 :(得分:3)
成员对象以它们构造的相反顺序被销毁。请注意,您不会通过更改构造函数初始化列表中的顺序来影响此顺序。订单完全由您在struct / class定义中声明它们的顺序决定。
我不知道的是,为A调用析构函数的顺序是什么。分别是aa,aa,aaa还是aaa,aa,a?
因此,后一种情况正在发生。
答案 1 :(得分:1)
一切都很好看。它以堆栈方式构造 - 破坏(先入/最后出):
#include <iostream>
struct A
{
A() { name="untitled"; std::cout << name <<" constructor" << std::endl; }
A(std::string name):name(name) { std::cout << name <<" constructor" << std::endl; }
~A() { std::cout << name <<" destructor" << std::endl; }
std::string name;
};
struct B
{
A a, aa, aaa;
B() : aa("aa"), a("a") { std::cout << "B constructor" << std::endl; }
~B() { std::cout << "B destructor" << std::endl; }
};
B beta;
int main()
{
return 0;
}
结果:
a constructor
aa constructor
untitled constructor
B constructor
B destructor
untitled destructor
aa destructor
a destructor
这个订单有保证吗? yes
如果您打开所有警告,您会看到:
g++ -Wall -Wreorder main.cpp
main.cpp: In constructor ‘B::B()’:
main.cpp:12:10: warning: ‘B::aa’ will be initialized after [-Wreorder]
A a, aa, aaa;
^
main.cpp:12:7: warning: ‘A B::a’ [-Wreorder]
A a, aa, aaa;
^
main.cpp:13:5: warning: when initialized here [-Wreorder]
B() : aa("aa"), a("a") { std::cout << "B constructor" << std::endl; }
^
答案 2 :(得分:1)
这需要永远来查找,但是根据n4659(ISO C ++ 17草案):
15.6.2初始化基础和成员
第(13.3)段
然后,非静态数据成员按照它们在类定义中声明的顺序进行初始化(同样不管mem-initializers的顺序如何)。
[注意:声明命令的目的是确保基础和成员子对象在销毁中被销毁 初始化的逆序。 - 结束说明]
这里,mem-initializers
是构造函数定义中冒号后面的列表。