下面的代码生成一个悬空引用,从编译器发出的警告中可以看出,函数中A
对象的析构函数g()
在函数返回之前被调用。还可以验证在main()
“使用堆栈”之后,返回的引用有垃圾,至少在调试版本中是这样。但我无法在发布版本中重现相同的行为。这是为什么?编译器在这里做了什么样的优化,给人一种引用没问题的印象r
?
#include <iostream>
struct A{
A(int i) : i(i) { std::cout << "Ctor\n"; }
A(const A& a) { i = a.i; std::cout << "Copy ctor\n"; }
~A() { std::cout << "Dtor\n"; }
int i;
};
A& g(int i) { A x(i); return x; }
int main()
{
const A& r = g(1);
std::cout << "Using the stack\n";
std::cout << r.i << '\n'; // r.i has garbage in debug, but not in a release build.
}
PS。我反对 NRVO,因为该函数不返回A
对象。
编辑:回应马克托洛宁。即使我const A& r = g(1);
在发布构建后包含这些表达式也不会显示垃圾std::cout << r.i << '\n';
std::cout << "Using the stack ...................................................................................................................\n";
std::cout << "Using the stack ...................................................................................................................\n";
std::cout << "Using the stack ...................................................................................................................\n";
std::cout << "Using the stack ...................................................................................................................\n";