有人可以告诉test(2)
调用后test_method()
对象被销毁的原因吗?
#include<iostream>
#include<string>
using namespace std;
class test
{
int n;
public:
test(int n) : n(n)
{
cout << "test: " << n << endl;
}
~test()
{
cout << "~test: " << n << endl;
}
test & test_method()
{
cout << "test_method: " << n << endl;
return *this;
}
};
int main(int argc, const char *argv[])
{
cout << "main start" << endl;
const test &test1 = test(1);
const test &test2 = test(2).test_method();
cout << "main end" << endl;
}
输出是:
main start
test: 1
test: 2
test_method: 2
~test: 2
main end
~test: 1
答案 0 :(得分:6)
test(2).test_method()
返回一个绑定到test2
的引用,然后它引用的对象在完整表达式的末尾被销毁,因为它是一个临时对象。 那不应该是一个惊喜。
真正的惊喜是test1
仍然是有效的引用,因为它直接绑定到临时,并且临时绑定到引用将临时的生命周期延长到参考变量。
您只需要注意,在test(2)
情况下,临时对象不会绑定任何内容。它只是用于调用某个成员函数,然后完成它的工作。它不会“照看”成员函数,换句话说,终生扩展不会通过所有可能的未来引用传递。
这是一个简单的思想实验,为什么实际上不可能实现“任意生命延长”:
extern T & get_ref(T &);
{
T const & x = get_ref(T());
// stuff
// Is x still valid?
}
我们不知道x
是否在第一行之外仍然有效。 get_ref
可以做任何事情。如果它被实现为T & get_ref(T & x) { return x; }
,我们可能希望有魔力,但也可能是这样:
namespace { T global; }
T & get_ref(T & unused) { return global; }
无法在原始翻译单元内决定是否需要扩展任何内容。所以标准目前的方式是,这是一个完全无关紧要的本地决策,只是在查看引用声明表达式时才会产生,临时对象的生命周期应该是什么。
答案 1 :(得分:0)
因为C ++标准需要这种行为。如果要保留对象,请为该对象指定名称。只要名称,它就会持续存在。
编辑:您的示例,test1
是您为第一个对象指定的名称,而第二个对象根本没有获得名称,因此它不会超过评估表达。