首页 > 解决方案 > 对临时对象的 const 引用不会延长其生命周期

问题描述

我有一个类,我从中创建一个临时对象。我可以将 const 引用绑定到这个临时对象,它按预期工作。但是,如果我在这个临时对象上调用一个返回 std::move(*this) 的成员函数,并绑定到这个返回值,它就不会像我预期的那样工作。下面的短代码重现了我的问题并且不言自明。

#include <iostream>
#include <cstdlib>
#include <vector>

class myval {
    public:
    std::vector<int> i;
    myval(int i) : i({i}) {}
    myval(const myval& v) = delete;
    myval(myval&& v) : i(std::move(v.i)) {}
    myval&& addone() && {
        i[0]++;
        return std::move(*this);
    }

};

int main()
{
    //Object is moved, works like expected
    const auto moved_value = myval{7}.addone();
    std::cout << moved_value.i[0] << std::endl;

    //Const reference is supposed extend the lifetime of a temporary object
    const auto& u = myval{7};
    //Prints 7, as expected
    std::cout << u.i[0] << std::endl;

    const auto& v = myval{7}.addone();
    //Why does this print 0?
    std::cout << v.i[0] << std::endl;

    return 0;
}

编辑:

  1. 鉴于对此的解释可能是什么,是否有可能使这项工作使作业“ const auto& v = ....”起作用?

  2. 为什么以下作业有效,而我的无效?

    const auto& s = std::string("hi")[1];
    std::cout << s;
    

标签: c++c++14c++17

解决方案


const 引用仅延长函数本地临时对象的生命周期。在行

const auto& v = myval{7}.addone();

您的参考不绑定到临时。 addone通过引用返回,这意味着您正在使用左值而不是临时值,因此当完整表达式结束时,您将获得对不再存在的对象的引用。


关于编辑。做

const auto& v = myval{7}.addone();

我会更改addone为按值返回,例如

myval addone() && {
    i[0]++;
    return std::move(*this);
}

然后,这将为您提供正确的行为,因为它将对象移动到一个临时对象中,然后您可以延长生命周期。

为了

const auto& s = std::string("hi")[1];
std::cout << s;

你的代码有未定义的行为,不幸的是你得到了你所期望的。您正在做与前面的示例相同的事情,并且您创建的临时字符串没有生命周期延长。


推荐阅读