您提到的引用专门用于从函数返回引用并将该引用绑定到临时:
const T& f() { return T(); };
在您的代码中不是这种情况,因为您将临时绑定到调用端的引用,而不是在 return 语句中。在您的评论中,您提到当您将代码修改为:
T f() { return T(); }
T&& r = f();
寿命仍然延长,但这是错误的。临时对象在return
语句的持续时间内存在,在此期间它被复制到返回值。复制完成后,临时结束的生命周期。在调用方,您有一个不同的临时(的结果f()
),其生命周期得到延长。
但毫无疑问,临时工的寿命会延长。如果您使用任何消息为类 A 定义析构函数,它将在 main() 的末尾打印,还是在那里?
这种说法也是不正确的。您正在看到返回值优化 (RVO) 的效果。编译器没有为函数内部创建一个临时对象T()
并为返回值创建另一个对象,而是在同一位置创建这两个对象。您可能在程序的输出中看到一个对象,但理论上有两个。
您可以尝试将 g++ 与 -fno-elide-constructors 一起使用,您应该能够看到两个临时对象,其中一个已扩展,另一个不会。
或者,您可以返回参考:
const A& f() { return A(); }
const A& r = f();
这应该显示临时死机在r
超出范围之前是如何死亡的。
这基本上是相同的测试抑制
$ g++ --版本 | 头-1
g++ (GCC) 4.3.2
$猫x.cpp
#include <iostream>
struct X {
X() { std::cout << "X\n"; }
~X() { std::cout << "~X\n"; }
};
X f() { return X(); }
int main() {
const X& x = f();
std::cout << "still in main()\n";
}
$ g++ -o t1 x.cpp && ./t1
X
still in main()
~X
$ g++ -fno-elide-constructors -o t2 x.cpp && ./t2
X
~X
still in main()
~X
$ clang++ -版本 | 头-1
$ clang 3.2 版 (tags/RELEASE_32/final)
$ clang++ -fno-elide-constructors -o t3 x.cpp && ./t3
X
~X
still in main()
~X
$猫y.cpp
#include <iostream>
struct X {
X() { std::cout << "X\n"; }
~X() { std::cout << "~X\n"; }
};
const X& f() { return X(); }
int main() {
const X& x = f();
std::cout << "still in main()\n";
}
$ g++ -fno-elide-constructors -o t4 y.cpp && ./t4
X
~X
still in main()