修改临时对象

Modyfying temporary object

本文关键字:临时对象 修改      更新时间:2023-10-16

有人能说出为什么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

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; }

原始翻译单元中无法决定是否需要扩展任何内容。因此,该标准目前的方式是,这是一个完全微不足道的本地决定,只是在查看引用声明表达式时做出的,所讨论的临时对象的生存期应该是多少。

因为C++标准需要此行为。 如果希望对象持久化,请为其命名。 它将持续到名称。

编辑:您的示例,test1是您为第一个对象指定的名称,而第二个对象根本没有获得任何名称,因此它不会超过表达式的计算时间。