自动对象(在堆栈上创建的对象)的销毁是否可以保证在 之前超出范围执行?
澄清:
#include <iostream>
class A {
public:
A() {
std::cout << "1";
}
~A() {
std::cout << "3";
}
};
void test123() {
A a;
std::cout << "2";
}
要打印"2"
,不再需要a
,因此从理论上讲,编译器可以在不再需要时尽快优化并销毁a
。
我可以依赖上述功能始终打印123
?
答案 0 :(得分:9)
严格定义堆栈对象的销毁顺序 - 当您离开作用域时(通过在{}
的末尾运行,或通过return
,它们以与声明相反的顺序执行,或者通过例外)。因此,您总是在那里看到123
。
但请注意,编译器优化由“as-if”规则控制。换句话说,编译器可以尽早销毁对象,只要生成的程序表现为'as-if'它在正常时被销毁。在这种情况下,因为您输出,编译器必须在适当的时间安排输出。但是,如果您有delete
da指向基本类型的指针,并且编译器可以证明没有其他未指向该值的指针,那么它原则上可以先移动delete
。关键是没有符合要求的程序能够注意到这种优化。
答案 1 :(得分:3)
标准确定该代码的正确行为是打印“123”。允许编译器根据需要更改代码,同时保持相同的语义( as-if 规则),并且此处对代码的重新排序将改变语义,因此不允许兼容的编译器做到这一点。
答案 2 :(得分:0)
构造函数可能有副作用。例如,它们可能实现互斥锁,即构造函数锁定,并且desctuctor解锁互斥锁。因此需要123.