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)
{
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;
}
}
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).