La norme C de ne garantit une commande pour les listes d'initialisation (standard ISO C++ 12.6.2/5):
... membres de données non statiques doivent être initialisés dans l'ordre où ils ont été déclarés dans la définition de classe (encore une fois sans tenir compte de l'ordre des mém-initialisateurs).
(Voir Wyatt Anderson's answer pour plus d'informations.)
Exemple:
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!
}
Cependant, vous ne pouvez pas initialiser une variable deux fois - ce que vous avez ne compilera pas.
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_))
{
}
Au lieu de cela, il suffit de mettre le travail supplémentaire dans le constructeur:
X::X() : impl_(Allocate(sizeof(X_Implementation)))
{
impl_ = Construct<X_Implementation>(impl_);
}
Il peut y avoir des problèmes de sécurité d'exception avec le code ci-dessus, mais sans savoir ce Allocate()
ou Construct()
ne fait I » Je ne peux pas dire. Je peux vous dire qu'il est préférable de séparer l'allocation et la construction dans leurs propres classes si vous faites cela, en utilisant l'acquisition de ressources Est Initialisation (RAII) de langage:
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
}
};
De cette façon, si Construct()
jette une exception, vous ne perdrez pas de mémoire car le destructeur de classe de base sera appelé, ce qui libèrera la mémoire pointée par impl_
. Ceci est important car si l'exception n'est pas interceptée et quitte le constructeur, son destructeur correspondant ne sera pas appelé. Voir le document de Bjarne Stroustrup sur exception sécurité: http://www2.research.att.com/~bs/except.pdf
Utilisez le placement new à construire dans un tampon mémoire que vous avez précédemment alloué. –
Vous ne pouvez pas initialiser un objet plus d'une fois, cette question est donc non-séquentielle. Au-delà de cela, une copie évidente de [Ordre d'évaluation de la liste d'initialisation du constructeur] (https://stackoverflow.com/questions/1242830/constructor-initialization-list-evaluation-order) –