serie La C++ fa garantire un ordine per le liste di inizializzazione (ISO C++ standard 12.6.2/5):
... membri dati non statici vengono inizializzati nell'ordine in cui sono state dichiarate nel definizione della classe (di nuovo indipendentemente dall'ordine degli inizializzatori di mem ).
(Vedi Wyatt Anderson's answer per ulteriori informazioni.)
Esempio:
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!
}
Tuttavia, non è possibile inizializzare una variabile due volte - quello che hai non verrà compilato.
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_))
{
}
Invece, appena messo il lavoro in più nel costruttore:
X::X() : impl_(Allocate(sizeof(X_Implementation)))
{
impl_ = Construct<X_Implementation>(impl_);
}
Ci possono essere problemi di sicurezza eccezione con il codice di cui sopra, ma senza sapere cosa Allocate()
o Construct()
fa in realtà io' Non sono in grado di dirlo. Vi posso dire che è meglio separare l'allocazione e la costruzione nelle proprie classi se si fa questo, utilizzando il Resource acquisizione è di inizializzazione (Raii) idioma:
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
}
};
questo modo, se Construct()
genera un'eccezione, non si perde memoria poiché verrà chiamato il distruttore della classe base che assegnerà la memoria puntata da impl_
. Questo è importante perché se l'eccezione non viene catturata e lascia il costruttore, il relativo distruttore di corrispondenza non verrà chiamato. Vedere Carta di Bjarne Stroustrup sulla sicurezza rispetto alle eccezioni: http://www2.research.att.com/~bs/except.pdf
Utilizzare il nuovo inserimento per creare un buffer di memoria precedentemente assegnato. –
Non è possibile inizializzare un oggetto più di una volta, quindi questa domanda è un non sequitur. Oltre a ciò, ovvio duplicato di [Ordine di valutazione elenco di inizializzazione costruttore] (https://stackoverflow.com/questions/1242830/constructor-initialization-list-valutazione-valutazione) –