【问题标题】:Returning const reference to temporary behaves differently than local const reference?将 const 引用返回到临时的行为与本地 const 引用不同?
【发布时间】:2020-09-20 08:31:13
【问题描述】:

我试图更好地了解如何将左值和右值作为引用处理,因此我创建了这个玩具示例:

#include <iostream>

struct Val
{
    Val(int num) : num(num){};
    ~Val()
    {
        std::cout << "Destructing with value " << num << std::endl;
    }

    int num;
};

const Val &test(const Val &val)
{
    return val;
}
int main()
{
    std::cout<< "Creating foo with value 5" <<std::endl;
    const Val &foo = test(Val(5));
    std::cout<< "Creating bar with value 3" <<std::endl;
    const Val &bar(3);
    std::cout<< "Finishing main function" <<std::endl;
    return 0;
}

打印出来:

Creating foo with value 5
Destructing with value 5
Creating bar with value 3
Finishing main function
Destructing with value 3

基本上我们看到这个右值Val(5) 绑定到函数val 中的常量引用参数test,并且返回了相同的值——但是,析构函数被立即调用,因为它是一个临时的。但是当我们尝试构造 Val(3) 并分配给一个 const 引用时,它仍然在整个块的范围内。

我的想法是,我们可以将右值绑定到 const 引用,这将延长它们的生命周期,直到该引用超出范围,但这里似乎不一定如此。如果能深入了解我的误解,我将不胜感激。

【问题讨论】:

    标签: c++ reference lifetime temporary


    【解决方案1】:

    给定const Val &amp;foo = test(Val(5));,临时的Val(5) 将在完整表达式后立即销毁,其生命周期不会延长到引用foo 的提升时间。不是直接绑定foo,而是绑定test的引用参数。

    reference initialization

    (强调我的)

    每当引用绑定到临时对象或子对象时 其中,临时的生命周期被延长以匹配 引用的生命周期,但以下情况除外:

    • 在函数调用中的引用参数的临时绑定一直存在,直到包含该函数调用的完整表达式结束:如果 该函数返回一个引用,该引用比完整表达式的寿命长, 它变成了一个悬空引用。

    一般来说,临时的生命周期不能通过以下方式进一步延长 “传递它”:第二个引用,从对的引用初始化 临时绑定的,不影响其生命周期。

    【讨论】:

      【解决方案2】:

      我的想法是,我们可以将右值绑定到 const 引用,这将延长它们的生命周期,直到该引用超出范围

      是的,确实val 参数确实 延长了Val(5) 的生命周期,但是当test 返回时,val 本身被破坏了,没有任何东西可以让Val(5) 活着,所以它也被摧毁了。

      通过引用返回实际上是在返回一个悬空引用,所以你有未定义的行为:参数val是对实际参数Val(5)的引用并不影响事实上,valtest 返回后不再可用,并且您通过引用返回(嗯,试图返回)it (val),而不是它的引用实体。

      【讨论】:

        【解决方案3】:

        当您向 test() 本身添加输出时

        const Val &test(const Val &val)
        {
            std::cout << "test with value " << val.num << '\n';
            return val;
        }
        

        你会看到,临时的存在直到函数结束,但不会超过

        Creating foo with value 5
        test with value 5
        Destructing with value 5
        Creating bar with value 3
        Finishing main function
        Destructing with value 3
        

        【讨论】:

          猜你喜欢
          • 2023-03-30
          • 1970-01-01
          • 2015-05-23
          • 2010-10-20
          • 1970-01-01
          • 1970-01-01
          • 2012-07-18
          • 2019-07-02
          • 2017-11-13
          相关资源
          最近更新 更多