C++ - 如果一个对象在循环中声明,它的析构函数是在循环结束时调用的吗?

Jen*_*ars 14 c++ loops class object

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

while(some_condition)
{
    SomeClass some_object;
    some_object.someFunction();
    some_variable = some_object.some_member;
}
Run Code Online (Sandbox Code Playgroud)

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

谢谢.

Rob*_*obᵩ 26

是.

但你可以亲自测试一下.这是一种语言功能,编译器不太可能出错.

#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;
  }
}
Run Code Online (Sandbox Code Playgroud)


Fle*_*exo 8

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

关于优化的通常规则仍然适用.如果编译器是智能的并且对象简单,那么编译器可以做任何它仍然产生正确行为的事情,例如:

#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;
  }
}
Run Code Online (Sandbox Code Playgroud)

编译为:

.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
Run Code Online (Sandbox Code Playgroud)

即展开并且没有那个析构函数的迹象(虽然可观察的行为仍然是相同的).

  • 在我的系统上生成的代码,如果该成员比一个int更复杂并且根据循环计数器而变化是非常有趣的 - 基本上你最终得到的内存用于生成二进制文件的`foo`的每个单独实例化,预先计算. (3认同)