2012-04-30 9 views
12

En C++, se llama al destructor de un objeto al cerrar "}" para el bloque en el que se creó, ¿no? Así que esto significa que si tengo:C++ - Si un objeto se declara en un bucle, ¿se llama al destructor al final del bucle?

while(some_condition) 
{ 
    SomeClass some_object; 
    some_object.someFunction(); 
    some_variable = some_object.some_member; 
} 

A continuación, el destructor del objeto creado en una iteración del bucle se llama al final del bucle antes de crear otro objeto, correcto?

Gracias.

+0

posible duplicado de [duración de la declaración dentro de un bucle] (http://stackoverflow.com/questions/3768662/lifetime-of-declaration-within-a-loop) –

Respuesta

24

Sí.

Pero podría haberlo probado usted mismo. Esta es una característica del lenguaje que es poco probable que los compiladores se equivoquen.

#include <iostream> 

struct S { 
    S() { std::cout << "S::S()\n"; } 
    ~S() { std::cout << "S::~S()\n"; } 
}; 

int main() { 
    int i = 10; 
    while(i--) { 
    S s; 
    } 
} 
+0

Corto, dulce, correcto. == +1 – duffymo

+0

Aceptaré tu respuesta un poco una vez que la restricción de tiempo para aceptar me permita. –

+0

No lo sé, los compiladores son _realmente buenos_ al hacer las cosas mal ... :) +1 –

7

El comportamiento observable es que se llama cada iteración.

Sin embargo, se aplican las reglas habituales sobre optimizaciones. Si el compilador es inteligente y el objeto simple entonces compilador puede hacer lo que le gusta que aún produce el comportamiento correcto, por ejemplo .:

#include <iostream> 

struct foo { 
    int i; 
    foo() : i (-1) {} 
    ~foo() { i = 1; } 
}; 

int main() { 
    int i = 10; 
    while (--i) { 
    foo f; 
    std::cout << f.i; 
    } 
} 

compila en:

.Ltmp5: 
     .cfi_def_cfa_register %rbp 
     movl $_ZSt4cout, %edi 
     movl $-1, %esi 
     callq _ZNSolsEi 
     movl $_ZSt4cout, %edi 
     movl $-1, %esi 
     callq _ZNSolsEi 
     movl $_ZSt4cout, %edi 
     movl $-1, %esi 
     callq _ZNSolsEi 
     movl $_ZSt4cout, %edi 
     movl $-1, %esi 
     callq _ZNSolsEi 
     movl $_ZSt4cout, %edi 
     movl $-1, %esi 
     callq _ZNSolsEi 
     movl $_ZSt4cout, %edi 
     movl $-1, %esi 
     callq _ZNSolsEi 
     movl $_ZSt4cout, %edi 
     movl $-1, %esi 
     callq _ZNSolsEi 
     movl $_ZSt4cout, %edi 
     movl $-1, %esi 
     callq _ZNSolsEi 
     movl $_ZSt4cout, %edi 
     movl $-1, %esi 
     callq _ZNSolsEi 
     xorl %eax, %eax 
     popq %rbp 
     ret 

es decir, desenrollado y no hay señal de ese destructor allí (aunque el comportamiento observable sigue siendo el mismo).

+3

El código que se genera en mi sistema si el miembro es un poco más complejo que solo un int y varía según el contador de ciclos es bastante interesante, básicamente terminas con la memoria para cada instanciación individual de 'foo' que vive dentro del binario, precalculada. – Flexo

Cuestiones relacionadas