16

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

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

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

谢谢。

4

2 回答 2

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;
  }
}
于 2012-04-30T17:45:18.667 回答
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;
  }
}

编译为:

.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

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

于 2012-04-30T17:54:48.280 回答