стандарт C++ делает гарантировать заказ для списков инициализации (ISO C++ Standard 12.6.2/5):
... нестатические элементы данных должны быть инициализированы в порядке их объявлены в класс (опять же, независимо от порядка памяти-инициализаторов ).
(см 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()
фактически делает I» м не могу сказать. Я могу вам сказать, что лучше отделить распределение и строительство в свои классы, если вы сделаете это, используя Resource Acquisition Is Initialization (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_
. Это важно, потому что если исключение не поймано и покидает конструктор, его соответствующий деструктор не будет называться. Смотрите статью Бьерн Страуструп по безопасности исключений: http://www2.research.att.com/~bs/except.pdf
Используйте новое размещение для создания в буфер памяти, который вы ранее выделили. –
Вы не можете инициализировать объект более одного раза, поэтому этот вопрос является нелогичным. Помимо этого, очевидный дубликат [Порядок оценки списка инициализации конструктора] (https://stackoverflow.com/questions/1242830/constructor-initialization-list-evaluation-order) –