class D: A
{
B obj;
C obj2;
}
這裏的結構順序是什麼保證?類別組件的初始化順序
我知道d將A,B和C之後建造的,但我真正想知道的是A是否是保證 B或C之前建造,B甚至是保證是
D(): A(), B(), C()
{}
但這是否初始化器列表確定順序初始化的:C.
我知道你可以有一個明確的初始化器列表以前建造的?
另外,無論是否有任何組件有或沒有默認的構造函數?
class D: A
{
B obj;
C obj2;
}
這裏的結構順序是什麼保證?類別組件的初始化順序
我知道d將A,B和C之後建造的,但我真正想知道的是A是否是保證 B或C之前建造,B甚至是保證是
D(): A(), B(), C()
{}
但這是否初始化器列表確定順序初始化的:C.
我知道你可以有一個明確的初始化器列表以前建造的?
另外,無論是否有任何組件有或沒有默認的構造函數?
從C++ 03標準ISO/IEC 14882:2003(E)§12.6.2/ 5 [class.base。INIT]:
初始化按照下列順序進行:
- 首先,只對最派生類的構造如下所述,虛擬基類,應在它們出現在一個深度的順序進行初始化基類,其中「左到右」的向無環圖的左側-first到右遍歷是在派生類鹼說明符列表基類名稱的顯示順序。
- 然後,直接基類應按聲明順序進行初始化,因爲它們出現在基指定程序列表(不管成分初始化程序的順序如何)中。
- 然後,非靜態數據成員應在他們的類定義中聲明(再次不管MEM-初始化的順序)的順序進行初始化。
- 最後,構造函數的主體被執行。
[注:聲明順序的任務是確保基部和構件子對象在初始化時相反的順序被破壞。 ]
因此,在這種情況下,這樣保證了初始化的順序將是第一個基類A
,那麼子對象B
(因爲它第一次出現在類定義類成員的列表),然後子對象C
。初始化列表的順序是無關緊要的,因爲是是否有任何成員或不具有默認的構造函數,如果一個成員沒有一個默認的構造函數,它沒有明確的初始化列表初始化,那麼它有一個未指定的值。
但是,初始化程序列表確定初始化的順序嗎?
否。初始化列表不確定確定成員數據和基礎子對象的初始化順序。成員在其聲明的順序初始化,並且基礎子對象構建在其提及的順序 - 從左至右:
struct A : B, C {} //B is constructed before C
此外,基子對象的成員數據的初始化之前建造。在上述結構初始化
struct A : B, C
{
D d;
E e;
};
訂單:
B => C => d => e
subobject subobject member member
他們正以相反的順序破壞。
也許斷碼這個例子將幫助說明:
如果我定義一個類,像這樣:
class Connection {
boost::asio::tcp::ip::socket _socket;
boost::asio::io_service _io_service;
Connection() : _io_service(), _socket(_io_service)
{
}
};
這將在所有現代編譯失敗。由於_socket
首先被定義爲類成員,但初始化列表將嘗試首先初始化它,儘管初始化列表要求編譯器首先初始化_io_service
。但由於_io_service
尚未初始化(套接字構造函數依賴於初始化的_io_service
),所以_socket
的初始化將導致段錯誤。
也許有人可以引用標準中規定這種行爲的適當部分。
對於問題的後半部分,基類將始終在類自己的成員之前初始化。
你是什麼意思「現代編譯器」?由於至少TC3.0,我正在使用C++,並且我不記得一個編譯器的初始化順序錯誤。 – sbi
不要喊我! –