ejemplos descargar definicion compiler caracteristicas c++

c++ - descargar - Por qué se llama a destructor cuando se retrocede mediante goto



c++ manual (4)

Posible duplicado:
¿Utilizará goto variables de fugas?

En el siguiente ejemplo, cuando se llama a goto para ir "hacia atrás", se llama al destructor de A ¿Por qué es así? El objeto a no está saliendo de su ámbito, ¿verdad? ¿El estándar dice algo sobre este comportamiento con respecto a goto ?

void f() { start: A a; goto start; }


6.6 declaraciones de saltos [stmt.jump]

Párrafo 2:

Al salir de un alcance (sin embargo cumplido), los objetos con duración de almacenamiento automático (3.7.3) que se han construido en ese alcance se destruyen en el orden inverso a su construcción. [Nota: Para los temporales, ver 12.2. —Después de la nota] La transferencia fuera de un bucle, fuera de un bloque o de vuelta después de una variable inicializada con duración de almacenamiento automática implica la destrucción de objetos con duración de almacenamiento automática que están dentro del alcance en el punto transferido pero no en el punto transferido a . (Ver 6.7 para transferencias en bloques). [Nota: Sin embargo, el programa puede terminarse (por ejemplo, llamando a std :: exit () o std :: abort () (18.5)) sin destruir los objetos de clase con la duración del almacenamiento automático. - nota final]

Creo que la parte importante es:

o retroceder más allá de una variable inicializada con duración de almacenamiento automático implica la destrucción


Aquí hay una cita relevante de la norma. Incluso incluye un ejemplo que es casi idéntico al tuyo:

C ++ 11 6.7 Declaración de declaración [stmt.dcl]

2 Las variables con duración de almacenamiento automático (3.7.3) se inicializan cada vez que se ejecuta su declaración de declaración. Las variables con la duración del almacenamiento automático declarada en el bloque se destruyen al salir del bloque (6.6).

3 Es posible transferir a un bloque, pero no de una manera que evite las declaraciones con la inicialización. Un programa que salta de un punto donde una variable con duración de almacenamiento automático no está dentro del alcance a un punto donde está dentro del alcance está mal formado a menos que la variable tenga tipo escalar, tipo de clase con un constructor predeterminado trivial y un destructor trivial, un La versión cv calificada de uno de estos tipos, o una matriz de uno de los tipos anteriores y se declara sin un inicializador (8.5). [Ejemplo:

void f() { // ... goto lx; // ill-formed: jump into scope of a // ... ly: X a = 1; // ... lx: goto ly; // OK, jump implies destructor // call for a followed by construction // again immediately following label ly }

—En ejemplo]

Como se explica en el ejemplo, el goto implica destrucción. La declaración de declaración ( A a; en su código) significa que el constructor se vuelve a ejecutar después de cada salto.


En pocas palabras ... start: es una etiqueta y declara un alcance [nother]

Suponiendo que el start es como <0x00003000> , A a estará en <0x00003000> + some_offset decir <0x00003004> .

goto start le pedirá al PC (Program Counter) que vaya a la dirección de inicio que ocurre antes de la declaración de A - fuera de su alcance - por lo tanto, " destruir a " llama al destructor.


La vida útil del objeto a comienza a partir de su declaración y se extiende hasta el final del bloque que lo contiene.

Esto significa que, al saltar antes de la declaración, saltas a situaciones de marco de pila donde el local no existía, por lo que debe ser destruido

  1. El point of declaration para un nombre es inmediatamente después de su declarador completo (Cláusula 8) y antes de su inicializador (si corresponde), [...] (§ 3.3.2)

  2. Un nombre declarado en un bloque (6.3) es local a ese bloque; tiene ámbito de bloque. Su alcance potencial comienza en su punto de declaración (3.3.2) y termina al final de su bloque. Una variable declarada en el ámbito del bloque es una variable local. (§ 3.3.3)