通过构造函数初始化集初始化的变量的销毁顺序是什么?

问题描述:

假设我有类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对象被销毁,其中,所述部件被破坏的顺序是cba

如果您按照与声明不同的顺序初始化成员,则某些编译器会发出警告,并且保持一致性很好。

+0

是的,我现在明白了。所以,如果我混淆了声明/或初始化顺序的顺序,销毁顺序可能会变得混乱。保持声明和初始化之间的一致性是有意义的。我知道这个规则,但不知道它也适用于构造初始化集。 – rajshenoy 2012-08-02 06:59:42

+0

@rajshenoy好吧,破坏的顺序会改变,但它不会搞砸。它仍然是明确的。 :) – 2012-08-02 07:03:08

+0

@rajshenoy但是,如果你在我的例子中交换b和c,那么b首先会被销毁。 – 2012-08-02 07:03:37

它们总是以相反的顺序销毁。无论初始化程序列表中的顺序如何,构造顺序始终是声明的顺序。

成员(和非虚拟子对象)按其声明的顺序构建,并按相反顺序销毁。初始值设定项列表中的初始值设定项的顺序无关,但强烈建议保持相同,以保持自己和身边的每个人都清醒。

想象一下,你有这样的:Foo(int n) : a(n), b(a) { }。这看起来不错,但如果在Foo::a之前实际声明Foo::b,则这可能是未定义的行为(如果b的构造函数需要完整类型)。为了防止这种情况,您应该始终启用并遵守相关的编译器警告。

+2

这是否是UB取决于'b'的细节。如果'B :: B'只需要存储一个'A&',它就是明确的。一个类似的情况是将'* this'传递给成员对象,以便它知道它的父对象。这在构建之前也“提及”了一个对象。 – MSalters 2012-08-02 06:57:14

+0

@ MSalters:谢谢,好点!编辑。 – 2012-08-02 06:58:27