Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ - If an object is declared in a loop, is its destructor called at the end of the loop?

In C++, an object's destructor is called at the closing "}" for the block it was created in, right? So this means that if I have:

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

Then the destructor for the object created in one iteration of the loop will be called at the end of the loop before another object is created, correct?

Thanks.

like image 663
Jenny Shoars Avatar asked Apr 30 '12 17:04

Jenny Shoars


2 Answers

Yes.

But you could have tested it yourself. This is a language feature that compilers are unlikely to get wrong.

#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;
  }
}
like image 112
Robᵩ Avatar answered Oct 07 '22 13:10

Robᵩ


The observable behaviour is that it's called each iteration.

The usual rules about optimisations still apply though. If the compiler is smart and the object simple then compiler can do anything it likes that still produces the correct behaviour, e.g.:

#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;
  }
}

Compiles to:

.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

I.e. unrolled and no sign of that destructor in there (although the observable behaviour is still the same).

like image 8
Flexo Avatar answered Oct 07 '22 13:10

Flexo