C++ 修改临时对象

C++ 修改临时对象,c++,object,temporary,C++,Object,Temporary,有人能告诉我为什么test(2)对象在test\u method()调用后被销毁吗 #include<iostream> #include<string> using namespace std; class test { int n; public: test(int n) : n(n) { cout << "test: " << n << endl; } ~te

有人能告诉我为什么
test(2)
对象在
test\u 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;
}
test(2).test_method()
返回一个绑定到
test2
的引用,然后它所引用的对象在完整表达式的末尾被销毁,因为它是一个临时对象。这并不令人惊讶

真正令人惊讶的是,
test1
仍然是一个有效的引用,因为它直接绑定到一个临时变量,而将临时变量绑定到一个引用会将临时变量的生存期延长到引用变量的生存期

您只需注意,在
测试(2)
的情况下,临时对象没有绑定到任何东西。它只是用来调用一些成员函数,然后它的工作就完成了。它不是“babysit”成员函数,或者换句话说,生命周期扩展不是通过所有可能的未来引用传递的


下面是一个简单的思维实验,为什么不可能真正实现“任意延长寿命”:

我们不知道
x
在第一行之后是否仍然有效
get_ref
可以做任何事情。如果它被实现为
T&get_ref(T&x){return x;}
,我们可能希望有魔力,但也可能是这样:

namespace { T global; }
T & get_ref(T & unused) { return global; }

在原始翻译单元内,不可能决定是否需要扩展任何内容。因此,标准目前的做法是,它是一个完全琐碎的局部决策,只是在查看引用声明表达式时,应该考虑的是临时对象的生命周期。

< P>因为C++标准需要这种行为。如果希望对象持久化,请为其指定一个名称。它将持续存在,只要名称不变


编辑:您可以在示例中看到,
test1
是您给第一个对象的名称,而第二个对象根本没有名称,因此它不会超过表达式的计算时间。

std::cout
是缓冲的,因此它不是调试您想要解释的内容的更好方法。您知道标准的哪一部分对此进行了定义吗?
extern T & get_ref(T &);

{
    T const & x = get_ref(T());

    // stuff

    // Is x still valid?
}
namespace { T global; }
T & get_ref(T & unused) { return global; }