首页 > 解决方案 > 这个返回另一个临时对象的临时对象能活多久?

问题描述

考虑以下代码示例:

#include <iostream>

struct outer {

    struct ret {
        outer &a;
        ret(outer &a) : a(a) { }
        template <typename T>
        friend ret &operator<<(ret &r, const T &obj)
        {
            std::cout << "wrote: " << obj << std::endl;
            return r;
        }
        template <typename T>
        friend ret &&operator<<(ret &&r, const T &obj)
        {
            std::cout << "wrote: " << obj << std::endl;
            return std::move(r);
        }
        ~ret() { std::cout << "ret destroyed" << std::endl; }
    };

    template <typename T>
    ret operator<<(const T &obj)
    {
        std::cout << "starting." << std::endl;
        return ret(*this) << obj;
    }
    ~outer() { std::cout << "outer destroyed" << std::endl; }
};

它由两个嵌套结构组成,其中的外部返回内部的实例,而内部operator<<又具有返回对同一对象的(右值)引用的运算符重载。注意内部类的返回对象如何ret包含对外部对象的引用;构造时*this作为构造函数参数传递。

一种可能的使用方法是:

int main()
{
    outer b;
    b << 1 << 2 << 3;
    b << "abc";
}

这将按我的预期工作并打印

开始。
写道: 1
ret 销毁 // 这里控制从outer::operator<<
写道: 2
写道: 3
ret 销毁
开始。
写道: abc
ret 被毁
ret 被毁
外被毁

另一种方法是

int main()
{
    outer() << 1 << 2 << 3;
}

这也打印了预期的输出

开始。
写道: 1
ret 被毁
写道: 2
写道: 3
ret 被毁
外部被毁

但是,我想知道为什么类型的临时对象outer在程序结束时被销毁。

在这个例子中,这个由创建的临时对象是否有可能在该outer()行完成之前被销毁,从而使创建的ret对象具有对对象的悬空引用outer

我已经准备了一个关于godbolt的例子。

更新

为了回答@user4581301 的问题,该outer对象确实在 之后直接销毁,;而不是在main.

标签: c++lifetimecallstack

解决方案


推荐阅读