ejemplos descargar definicion compiler caracteristicas c++

c++ - descargar - ¿Por qué es ''int i=i;'' ¿legal?



c++ manual (4)

Posible duplicado:
int var = 1; void main () {int i = i; }

El siguiente código puede pasar la compilación tanto en g ++ como en Visual C ++. ¿Por qué es legal? Parece irrazonable y puede causar errores ocultos.

int main() { int i = i; }


La razón por la que está permitida por la sintaxis es que hay algunos casos impares en los que es posible que desee utilizar una variable por puntero o referencia en su propio inicializador:

struct ThingManager { void *thing; ThingManager(void *thing) : thing(thing) {} void Speak() { if (thing == (void*)this) { std::cout << "I''m managing myself/n"; } else { std::cout << "I''m managing " << thing << "/n"; } } }; ThingManager self_manager(&self_manager); ThingManager other_manager(&self_manager);

Así que C ++ le permite referirse a un objeto en su propia expresión de inicialización (su nombre está dentro del alcance). Entonces, como siempre en C ++, es su problema asegurarse de no usar realmente un valor no inicializado (su ejemplo, int i = i; usa un valor no inicializado).

Su compilador puede ayudar a identificar usos de valores no inicializados, pero el estándar no lo requiere.


Puede dejar que g++ advierta sobre este caso de uso con -Winit-self (junto con -Wuninitialized ), y si trata las advertencias como errores, debería satisfacer su comezón.

Esta técnica de usar el constructor de copia para autoinicializar a veces se usa para suprimir la ejecución del constructor / inicializador predeterminado de un objeto global. Esto puede ser necesario si el constructor predeterminado del objeto global es solo 0 inicializar el objeto, pero el objeto se usó antes de que se hubiera ejecutado el constructor. Como retroceso a C, los globales se inicializan a 0 al inicio del programa, y ​​luego el tiempo de ejecución de C ++ comienza a ejecutar constructores globales. Para aquellos casos estrechos en los que el constructor definido que se habría ejecutado es solo para poner fuera del objeto, la autoinicialización no hace ningún daño.

En el caso general, la autoinicialización del constructor de copias es una mala práctica, ya que generalmente causaría el mismo tipo de problemas que el uso de una variable no inicializada causaría (es decir, un comportamiento indefinido). En el ejemplo particular en la pregunta del OP, i es local a main , y por lo tanto no está inicializado. El resultado de leer una variable sin inicializar es siempre un comportamiento indefinido.


Puede usar cualquier variable previamente declarada como inicializador de otra variable.

En este caso, tan pronto como el compilador analiza int i , agrega eso a la tabla de símbolos, de modo que cuando ve el inicializador = i , el símbolo se puede resolver a partir de la declaración anterior.

No es un error porque el compilador puede darle sentido, ya que puede generar código que hace sin ambigüedades exactamente lo que especifica el código fuente, siete si es semánticamente sospechoso. La filosofía de C y C ++ es compilar cualquier cosa que pueda compilarse sintácticamente. Los errores semánticos generalmente solo emiten advertencias, y solo entonces si dichas advertencias están habilitadas.


EDIT: Es sintácticamente legal , pero resulta en un comportamiento indefinido si usas x .

No es legal porque está asignando una variable sin inicializar con otra variable sin inicializar (bueno, la misma). El hecho de que compile no significa que sea legal. Es válida la sintaxis de C ++, sí, pero no es legal.

El lado derecho del operador de asignación debe evaluarse completamente en el momento de la asignación. En este caso, esa es i , que no está inicializada.

Créditos a Steve Jessop, quien desenterró la cita:

4.1 / 1, lvalue a rvalue conversion

[...] si el objeto no está inicializado, un programa que necesita esta conversión tiene un comportamiento indefinido.