C++標準不保證初始化列表的順序(ISO C++標準12.6.2/5):
...非靜態數據成員應在他們在被宣佈 的順序 初始化類定義 (不管 mem初始化程序的順序如何)。
(有關詳細信息,請參閱Wyatt Anderson's answer。)
例子:
class Foo
{
public:
Foo();
private:
A a;
B b;
C c;
};
Foo::Foo() : b(), a(), c()
{
// a is initialized first, then b, then c - NOT b, a, then c!
}
但是,你不能初始化變量的兩倍 - 你不會編譯什麼。
class X //() what's with the pair of parentheses you have in your code snippet?
{
public:
X();
private:
X_Implementation* impl_;
};
X::X() :
impl_(Allocate(sizeof(X_Implementation))),
// It is not allowed to initialize a data member twice!
impl_(Construct<X_Implementation>(impl_))
{
}
相反,只是把額外的工作變成構造:
X::X() : impl_(Allocate(sizeof(X_Implementation)))
{
impl_ = Construct<X_Implementation>(impl_);
}
可能有例外安全問題與上面的代碼,但不知道什麼Allocate()
或Construct()
實際上做了我」米不能說。我可以告訴你,這是最好的配置和建設放在各自的類,如果你這樣做,使用資源獲取就是初始化(RAII)成語:
class XBase
{
protected:
XBase() : impl_(Allocate(sizeof(X_Implementation)))
{
}
~XBase()
{
if(impl_ != 0) { Deallocate(impl_); } // Or something like this
}
X_Implementation* impl_;
};
class X : private XBase // XBase is an implementation detail
{
public:
X()
{
impl_ = Construct<X_Implementation>(impl_);
}
~X()
{
Destruct<X_Implementation>(impl_); // Or something like this
}
};
這樣,如果Construct()
拋出一個異常,你將不會泄漏內存,因爲將調用基類析構函數,這將釋放由impl_
指向的內存。這很重要,因爲如果異常未被捕獲並且離開構造函數,則其匹配的析構函數將不會被稱爲。見了Bjarne Stroustrup的紙張上異常安全:http://www2.research.att.com/~bs/except.pdf
使用placement new構造到您之前分配的內存緩衝區中。 – 2010-10-27 22:11:36
你不能多次初始化一個對象,所以這個問題是不合適的。除此之外,[構造函數初始化列表評估順序]的明顯重複(https://stackoverflow.com/questions/1242830/constructor-initialization-list-evaluation-order) – 2017-11-04 15:58:35