Yo estaba escribiendo el código de hoy y tiene un extraño error de compilación, que parece ser causado por inicializar las variables miembro en un orden diferente al que fueron declarados.

Ejemplo:

class Test {
    int a;
    int b;

public:
    Test() : b(1), a(2) {
    }
};

int main() {
    Test test;
    return 0;
}

Luego si puedo compilar con -Werror -Wall:

$ g++ -Werror -Wall test.cpp
test.cpp: In constructor Test::Test()’:
test.cpp:3:9: error: Test::b will be initialized after [-Werror=reorder]
test.cpp:2:9: error:   int Test::a [-Werror=reorder]
test.cpp:6:5: error:   when initialized here [-Werror=reorder]
cc1plus: all warnings being treated as errors

Me doy cuenta de que -Wall es explícitamente pidiendo GCC para ir over-the-top con advertencias, pero supongo que hay una razón para todos ellos. Así que, ¿cómo podría el fin de inicializar las variables miembro de la materia?

InformationsquelleAutor Brendan Long | 2012-08-31

5 Comentarios

  1. 83

    La razón es porque son inicializados en el orden en que se declaró en su clase, no en el orden que se inicializa en el constructor y es un aviso de que el constructor de la orden no se utiliza.

    Esto es para ayudar a prevenir errores donde la inicialización de b depende de a o vice-versa.

    La razón de este orden es porque no es sólo un destructor, y tiene que elegir un «orden inverso» para destruir el miembro de la clase. En este caso, la solución más sencilla era la utilización de la orden de la declaración dentro de la clase para asegurarse de que los atributos que siempre fueron destruidos en el correcto orden inverso.

  2. 42

    ¿Por qué debo inicializar las variables miembro, en el orden en que se declaró en?

    Los miembros se ser inicializado en el mismo orden en que se declaran, lo quieras o no. La advertencia está diciendo que la orden que usted está pidiendo que difiere de la real orden de ejecución de inicialización.

    • +1 para una sucinta, al punto de contestar que no usa la palabra «compilador».
    • Bonita respuesta. Podemos asumir que esto es sólo el estándar de C++ asegurarse de que todos los constructores de compilar de manera determinista, o hay algún técnico/rendimiento razón por la que los miembros siempre deben ser inicializadas en el orden en que se declaró?
    • En el lenguaje, para todos, pero los objetos asignados dinámicamente, el orden de la construcción y de la destrucción se invierte. Si el orden de inicialización se determina por la lista de inicializador, a continuación, el orden de inicialización en una clase con varios constructores no sería definido y la orden de destrucción de los miembros no deberían ser definidos tanto. La razón por la que el orden de construcción/destrucción se invierte es para asegurarse de que si un objeto depende de la otra, la segunda no será destruido antes de que la primera.
    • Aha! Que está una buena razón – y yo no habría pensado. Gracias!
  3. 32

    No debería, ya que disminuye la legibilidad y es potencialmente engañoso.

    Si lo hizo:

    Test() : b(1), a(b) {}

    parece que b luego a se han definido para 1, mientras que en realidad el valor no inicializado de b se utiliza para inicializar a antes de b se inicializa a 1.

    • +1 para el ejemplo para mostrar por qué el orden en que realmente importa y lo que puede ir mal en caso de que alguien asume el orden es lo que han declarado en el constructor.
  4. 12

    Realidad el compilador siempre inicializa las variables en el orden de la declaración, incluso si usted escribe los inicializadores en un orden diferente. Por lo tanto, si usted no escribe las inicializaciones en el orden de la declaración, la orden de su inicializadores no encaja en el orden de inicialización, que puede conducir a pequeños errores en el caso de las inicializaciones dependen unos de otros.

    Por ejemplo, considere el código

    Test(): b(42), a(b) {}

    Este es un error porque a se inicializa antes de b, pero se ve ACEPTAR. Si se escribe en el orden de la declaración (que es el orden de inicialización), el error se presenta obvia:

    Test(): a(b), b(42) {}

    Nota de que el error también puede ser más sutil que eso; por ejemplo imaginemos a y b son de la clase de tipos que una salida algo en su constructor; luego, con el «incorrecta» la orden que se podría pensar que b‘s de salida debe aparecer antes de a‘s cuando en realidad la inversa que va a suceder. Si a‘s de salida aparece primero conducirá a un archivo no válido, que también es un error, pero no hay manera de que el compilador podría notar el problema si los constructores están en otra unidad de traducción (aparte del hecho de que el compilador no puede saber si la reordenación es o no es un error). Por lo tanto, es razonable que el compilador sólo advierte sobre cada instancia de la no-coincidencia de la orden.

  5. 5

    Me doy cuenta de que la Pared está explícitamente pidiendo GCC para ir over-the-top con advertencias, pero supongo que hay una razón para todos ellos.

    De la pared es sólo un comienzo. Contrario a lo que el nombre implica, la Pared no permite a todas las advertencias. Hay algunas advertencias que son sin duda «sobre la parte superior», pero esas son precisamente las advertencias de que la Pared no permite. Yo siempre uso la Pared, además de otros.

    Como para su queja, como otros ya han señalado, existe una muy buena razón de esta advertencia. Sólo porque usted especificar un orden no significa que el compilador utilizará ese orden. El orden en que el compilador debe utilizar por el estándar se basa en la definición de la clase.

Dejar respuesta

Please enter your comment!
Please enter your name here