通过构造函数初始化集初始化的变量的销毁顺序是什么?
假设我有类A,B和C通过构造函数初始化集初始化的变量的销毁顺序是什么?
如果我然后有容器如下
Container::Container()
:A(10),B(20),C(30)
{
//Do something specific
}
现在,如果我调用容器的析构函数,即〜集装箱() 我注意到,析构函数越来越按照相反的顺序调用 即〜C(),〜B()然后〜A()
这是什么东西总是固定的顺序? 任何人都可以抛出一些建设初始化集的析构函数的更多的灯光?
订单是固定的,但不是初始化列表。
这是成员在类中声明的相反顺序。
class Container
{
A a;
B b;
C c;
};
当Container
对象被销毁,其中,所述部件被破坏的顺序是c
,b
和a
。
如果您按照与声明不同的顺序初始化成员,则某些编译器会发出警告,并且保持一致性很好。
它们总是以相反的顺序销毁。无论初始化程序列表中的顺序如何,构造顺序始终是声明的顺序。
成员(和非虚拟子对象)按其声明的顺序构建,并按相反顺序销毁。初始值设定项列表中的初始值设定项的顺序无关,但强烈建议保持相同,以保持自己和身边的每个人都清醒。
想象一下,你有这样的:Foo(int n) : a(n), b(a) { }
。这看起来不错,但如果在Foo::a
之前实际声明Foo::b
,则这可能是未定义的行为(如果b
的构造函数需要完整类型)。为了防止这种情况,您应该始终启用并遵守相关的编译器警告。
这是否是UB取决于'b'的细节。如果'B :: B'只需要存储一个'A&',它就是明确的。一个类似的情况是将'* this'传递给成员对象,以便它知道它的父对象。这在构建之前也“提及”了一个对象。 – MSalters 2012-08-02 06:57:14
@ MSalters:谢谢,好点!编辑。 – 2012-08-02 06:58:27
是的,我现在明白了。所以,如果我混淆了声明/或初始化顺序的顺序,销毁顺序可能会变得混乱。保持声明和初始化之间的一致性是有意义的。我知道这个规则,但不知道它也适用于构造初始化集。 – rajshenoy 2012-08-02 06:59:42
@rajshenoy好吧,破坏的顺序会改变,但它不会搞砸。它仍然是明确的。 :) – 2012-08-02 07:03:08
@rajshenoy但是,如果你在我的例子中交换b和c,那么b首先会被销毁。 – 2012-08-02 07:03:37