С++. Если объект объявлен в цикле, его деструктор называется в конце цикла?
В С++ деструктор объекта вызывается при закрытии "}" для блока, в котором он был создан, правильно? Таким образом, это означает, что если у меня есть:
while(some_condition)
{
SomeClass some_object;
some_object.someFunction();
some_variable = some_object.some_member;
}
Затем деструктор для объекта, созданного на одной итерации цикла, будет вызываться в конце цикла до создания другого объекта, правильно?
Спасибо.
Ответы
Ответ 1
Да.
Но вы могли бы проверить его самостоятельно. Это языковая функция, что компиляторы вряд ли ошибаются.
#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;
}
}
Ответ 2
Наблюдаемое поведение состоит в том, что он вызывает каждую итерацию.
Обычные правила об оптимизации все еще применяются. Если компилятор умный, а объект простой, то компилятор может делать все, что ему нравится, что все еще создает правильное поведение, например:
#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;
}
}
Скомпилируется:
.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
т.е. разворачивается и нет признаков этого деструктора (хотя наблюдаемое поведение остается тем же).