2009-11-21 9 views
8

En el siguiente fragmento de código, el inicializador de d1 se pasa d2 que aún no se ha construido (¿correcto?), ¿Es el d.j en el constructor de copias de D un acceso de memoria no inicializado?¿El orden de inicialización está garantizado por la norma?

struct D 
{ 
    int j; 

    D(const D& d) { j = d.j; } 
    D(int i) { j = i; } 
}; 

struct A 
{ 
    D d1, d2; 
    A() : d2(2), d1(d2) {} 
}; 

¿Qué sección de C++ estándar discute el orden de inicialización de los miembros de datos?

+0

Pregunta relacionada aunque no duplicada: http://stackoverflow.com/questions/1589950/initializer-list-argument-evaluation-order –

Respuesta

11

No tengo el manual a la mano en este momento, así que no puedo citar la sección, pero la estructura o la inicialización del miembro de la clase siempre ocurre en orden de pedido. El orden en el que se mencionan los miembros en la lista de inicializadores del constructor no es relevante.

gcc tiene una advertencia -Wreorder que avisa cuando la orden es diferente:

 
     -Wreorder (C++ only) 
      Warn when the order of member initializers given in the code does 
      not match the order in which they must be executed. For instance: 

        struct A { 
        int i; 
        int j; 
        A(): j (0), i (1) { } 
        }; 

      The compiler will rearrange the member initializers for i and j to 
      match the declaration order of the members, emitting a warning to 
      that effect. This warning is enabled by -Wall. 
+5

La razón de esto es que las cosas se destruyen en el orden inverso en que se construyen. No puede cambiar el orden en que los miembros se destruyen después del destructor, por lo tanto, la orden construida * debe * corresponderse. – GManNickG

+2

Sin embargo, puede referirse a los miembros inicializados previamente, como se describe aquí: http://www.parashift.com/c++faq-lite/ctors.html#faq-10.7 – Jherico

+1

La explicación de las preguntas frecuentes en este caso es bastante útil, Creo; el estándar dice "hay un punto de secuencia después de la inicialización de cada base y miembro" (12.6.2/3). –

1

Sí. Un buen compilador debería advertirle que A::d2 se inicializará después de A::d1.

6

En su ejemplo fallará:

struct A 
{ 
    D d1, d2;  
    A() : d2(2), d1(d2) {} 
}; 

d1: is initialised first as it is declared first. 
d2: is then initialized. 

Como resultado, la lista de inicialización construirá d1 usando una referencia a un objeto no válido (d2).

Este es un motivo para aumentar el nivel de advertencia de los compiladores tan alto como sea posible.
Y, además, forzarlo a informar todas las advertencias como errores.

2

Este fenómeno se explica/resalta en el artículo 13 de Meyer's Effective C++. Dice que el destructor debe destruir elementos en el orden inverso de sus constructores, por lo tanto, todos los constructores deben inicializar elementos en el mismo orden, por lo tanto, los inicializan en el orden en que se declaran (en lugar de la secuencia de las listas de inicialización) .

11

El C++ estándar (ISO/IEC 14882: 2003 12.6.2/5, bases Inicialización y miembros) dice:

Inicialización procederá en el siguiente orden:

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

- Entonces, las clases base directas se inicializarán en orden de declaración tal como aparecen en la lista especificadora de bases (independientemente del orden de los iniciadores de memoria).

- A continuación, los miembros de datos no estáticos se inicializarán en el orden en que se declararon en la definición de clase (de nuevo, independientemente del orden de los iniciadores de memoria).

- Finalmente, se ejecuta el cuerpo del constructor.

El punto de viñeta 3 garantiza el orden de inicialización de los miembros de datos no estáticos.

Cuestiones relacionadas