终身扩展,prvalues和xvalues

时间:2017-02-24 15:00:11

标签: c++ c++11 xvalue prvalue value-categories

遵循这个问题的公认答案Do rvalue references allow dangling references?当分配给问题中的右值引用左值时,xvalues似乎没有延长其生命周期。但是当我这样做时

#include <iostream>

using namespace std;

class Something {
public:
    Something() {
        cout << "Something()" << endl;
    }
    Something(const Something&) {
        cout << "Something(const Something&)" << endl;
    }
    Something(Something&&) {
        cout << "Something(Something&&)" << endl;
    }
    ~Something() {
        cout << "~Something()" << endl;
    }

    int a;
};

Something make_something() {
    return Something{};
}

int main() {
    auto&& something = make_something().a;

    return 0;
}

make_something调用返回的对象的生命周期进行了扩展,即使make_something().ahttp://en.cppreference.com/w/cpp/language/value_category的xvalue(xvalues解释中的第三个项目符号列出了成员访问权限)我在上面作为xvalue,)

  

a.m,对象表达式的成员,其中a是rvalue,m是a   非引用类型的非静态数据成员;

如果值类别没有确定rvalue的生命周期何时会延长那么呢?我很难理解rvalue的生命周期何时在C ++中扩展

2 个答案:

答案 0 :(得分:4)

终身延期不关心价值类别。如[class.temporary] / p6所述:

  

引用绑定的临时值或作为绑定引用的子对象的完整对象的临时值在引用的生命周期内持续存在

强调补充。

这里没有说明所引用表达式的值类别。

确定临时是否延长的内容恰好是上述(以及更多规则)。

  

但这并不能解释为什么在分配引用的临时值周围添加std::move()不会延长生命周期

std::move不是C ++中一个神奇的,编译器定义的构造。它是一个函数调用,因此它的行为与任何其他C ++函数调用没有区别。

所以,如果你有std::move(Type()),那是什么意思?这意味着您将创建一个临时文件,将其绑定到std::move参数,然后调用该函数,这将返回一些内容。

将临时绑定到函数参数,如[class.temporary] / p6中所述,意味着临时的生命周期固定为创建它的完整表达式的生命周期(如果不是该规则,则在函数调用结束时必须销毁临时文件,因为那是参考文件生命周期的结束。

功能的作用,说或暗示并不重要。如果编译器可能内联并确定返回值是对来自临时的参数的引用,则无关紧要。该临时的生命周期固定在表达式上,而不是扩展。

答案 1 :(得分:1)

  

如果值类别没有确定rvalue的生命周期何时会延长那么呢?我很难理解rvalue的生命周期何时在C ++中扩展

请注意,值类别描述表达式而非对象。值类别(xvalue,prvalue或其他)不会以任何方式扩展。只有对象可以有生命周期。

来自n4296标准草案:

  • §12.2.1
      

    类类型的临时代码在各种上下文中创建:绑定对prvalue的引用(8.5.3),返回   prvalue(6.6.3),一个创建prvalue(4.1,5.2.9,5.2.11,5.4),抛出异常(15.1)的转换,   在一些初始化(8.5)。

  • §12.2.4
      

    有两种情况下,临时人员在不同时刻被摧毁,而不是在完全结束时   表达。 [...]
      第二个上下文是引用绑定到临时的时间。引用所在的临时值   绑定或临时,它是绑定引用的子对象的完整对象,但仍然存在   在参考的生命周期

注意:我没有引用第一个上下文,因为它对这些问题有一些小修辞。斜体强调由我添加。

因此,根据引用的第一段,函数表达式 makesomething()值类别prvalue创建类的临时类型以上。
makesomething().a访问临时的完整子对象。根据上面消息的第二个上下文,将此临时值与引用绑定到延长的生命周期。

子对象a的生命周期与先前创建的临时对象的生命周期相关联,使其成为到期值(xvalue)。如果不通过将其绑定到引用来延长其生命周期,它将与临时类对象一起销毁。因此,在这种情况下,在;之后。