C++ - 如果在循环中声明对象,是否在循环结束时调用其析构函数

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

本文关键字:循环 结束 调用 析构函数 是否 对象 如果 声明 C++      更新时间:2023-10-16

在C++中,对象的析构函数在创建它的块的结束"}"处调用,对吗?所以这意味着如果我有:

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

那么在循环的一次迭代中创建的对象的析构函数将在循环结束时调用,然后再创建另一个对象,对吗?

谢谢。

是的。

但是你可以自己测试一下。这是编译器不太可能出错的语言功能。

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

可观察到的行为是它被称为每次迭代。

不过,有关优化的常规规则仍然适用。如果编译器很聪明并且对象简单,那么编译器可以做任何它喜欢的事情,仍然产生正确的行为,例如:

#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

即展开并且那里没有该析构函数的迹象(尽管可观察到的行为仍然相同(。