4

自动对象(在堆栈上创建的对象)的销毁是否保证不会在超出范围之前执行?

澄清:

#include <iostream>

class A {
  public:
    A() {
      std::cout << "1";
    }
    ~A() {
      std::cout << "3";
    }
};

void test123() {
  A a;
  std::cout << "2";
}

不再需要print "2",因此理论上编译器可以在不再需要它时a尝试优化和销毁。a

我可以依靠上述功能始终打印123吗?

4

3 回答 3

10

堆栈对象的销毁顺序是严格定义的 - 当您离开范围时(通过运行结束{},或通过return,或通过异常),它们以声明的相反顺序执行。所以,你总会看到123那里。

但是请注意,编译器优化受“as-if”规则控制。换句话说,编译器可以提前销毁一个对象,只要生成的程序表现得“好像”它在正常时间被销毁了。在这种情况下,因为您进行输出,所以编译器必须在适当的时间安排输出。但是,例如,如果您有deleteda 指向原始类型的指针,并且编译器可以证明没有其他未完成的指向该值的指针,则原则上它可以将其移动得delete更早。关键是没有符合标准的程序能够注意到这种优化。

于 2011-08-28T20:37:53.027 回答
4

该标准确定该代码的正确行为是打印“123”。允许编译器在保持相同语义( as-if规则)的同时尽可能多地更改代码,并且在此处重新排序代码会更改语义,因此不允许兼容的编译器这样做。

于 2011-08-28T20:38:21.903 回答
0

构造函数可能有副作用。例如,他们可能实现互斥锁,即构造函数锁定,而析构函数解锁互斥锁。因此需要 123。

于 2011-08-28T20:41:29.327 回答