假設我有類A,B和C通過構造函數初始化集初始化的變量的銷燬順序是什麼?
如果我然後有容器如下
Container::Container()
:A(10),B(20),C(30)
{
//Do something specific
}
現在,如果我調用容器的析構函數,即〜集裝箱() 我注意到,析構函數越來越按照相反的順序調用 即〜C(),〜B()然後〜A()
這是什麼東西總是固定的順序? 任何人都可以拋出一些建設初始化集的析構函數的更多的燈光?
假設我有類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