2010-02-12 14 views
84

Oh gurús de C++, busco tu sabiduría. Hablar standardese a mí y decir a mis garantías si C++ que el siguiente programa:Orden del miembro constructor y llamadas al destructor

#include <iostream> 
using namespace std; 

struct A 
{ 
    A() { cout << "A::A" << endl; } 
    ~A() { cout << "A::~" << endl; } 
}; 

struct B 
{ 
    B() { cout << "B::B" << endl; } 
    ~B() { cout << "B::~" << endl; } 
}; 

struct C 
{ 
    C() { cout << "C::C" << endl; } 
    ~C() { cout << "C::~" << endl; } 
}; 

struct Aggregate 
{ 
    A a; 
    B b; 
    C c; 
}; 

int main() 
{ 
    Aggregate a; 
    return 0; 
} 

producirá siempre

A::A 
B::B 
C::C 
C::~ 
B::~ 
A::~ 

En otras palabras, son miembros garantizados para ser inicializado por orden de declaración y destruido a la inversa ¿orden?

+7

Esta es una causa razonablemente común de errores sutiles cuando las clases han crecido grandes y poco consolidadas. Cuando tiene 50 miembros de datos, y muchos de ellos se inicializan en la lista de intializadores del constructor, puede ser fácil suponer que el orden de construcción es el orden en la lista de inicializadores. Después de todo, los escritores de códigos han ordenado la lista con cuidado ... ¿verdad? – Permaquid

Respuesta

104

En otras palabras, ¿se garantiza la inicialización de los miembros por orden de declaración y se destruyen en orden inverso?

Sí a ambos. Ver 12.6.2

Inicialización procederá de la siguiente orden:

  • En primer lugar, y sólo para el constructor de la clase más derivada como se describe a continuación, base virtual las clases se inicializarán en el orden que aparezcan en un cruce de profundidad de izquierda a derecha del gráfico acíclico dirigido de la base clases, donde "de izquierda a derecha" es el orden de aparición de los nombres de la clase base de la clase base base-specifier-list.

  • Entonces, clases base directos se inicializan en orden de la declaración tal como aparecen en el especificador-lista de base (independientemente de el orden de los MEM-inicializadores).

  • A continuación, los miembros de datos no estáticos se inicializan en el orden en que fueron declarado en la definición de la clase (de nuevo sin tener en cuenta el orden de los MEM-inicializadores).

  • Finalmente, se ejecuta la declaración compuesta del constructor cuerpo. [Nota: el orden de la declaración es obligatorio para asegurarse de que los subobjetos base y miembros se destruyan en el orden inverso de la inicialización . nota -fin]

+0

Si mal no recuerdo, sí a ambos ... Piense en ello como una pila. Primero empujado, último golpe. Por lo tanto, al crear una instancia de su primera instancia, se inserta en la memoria en orden de una pila. Luego, el segundo es empujado, el tercero sobre el segundo y así sucesivamente. Luego, cuando destruyas tus instancias, el programa buscará el primero en destruir, el último que ha sido empujado. Pero podría estar equivocado al explicarlo de esta manera, pero es la forma en que lo aprendí al hacer C/C++ y ASM. –

5

Sí y sí. El orden de destrucción siempre es opuesto al orden de construcción, para las variables miembro.

26

Sí, son (miembros no estáticos). Ver 12.6.2/5 para la inicialización (construcción) y 12.4/6 para la destrucción.

+2

+1 para indicar que esto es para miembros _non-static_. :-) –

7

Sí, los objetos estándar garantiza quedar destruidos en el orden inverso al que fueron creados. La razón es que un objeto puede usar otro, por lo tanto, depende de él.Considere:

struct A { }; 

struct B { 
A &a; 
B(A& a) : a(a) { } 
}; 

int main() { 
    A a; 
    B b(a); 
} 

Si a eran antes de destruir bb luego sostendría un miembro de referencia válido. Al destruir los objetos en el orden inverso en el que fueron creados, garantizamos la destrucción correcta.

Cuestiones relacionadas