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.
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).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With