捣乱临时物体

Beg*_*End 4 c++ temporary object

有人可以告诉为什么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;
}
Run Code Online (Sandbox Code Playgroud)

输出是:

main start
test: 1
test: 2
test_method: 2

~test: 2
main end
~test: 1
Run Code Online (Sandbox Code Playgroud)

Ker*_* SB 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?
}
Run Code Online (Sandbox Code Playgroud)

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

namespace { T global; }
T & get_ref(T & unused) { return global; }
Run Code Online (Sandbox Code Playgroud)

在原始翻译单元内决定是否需要扩展任何内容是不可能的.所以标准目前的方式是它是一个完全无关紧要的本地决策,只是在查看引用声明表达式时才会产生,临时对象的生命周期应该是什么.