4

按照这个问题的公认答案右值引用是否允许悬空引用?当分配给问题中的右值引用左值时,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().a根据http://en.cppreference.com/w/cpp/language/value_category是一个 xvalue (xvalues 解释中的第三个项目符号列出了成员访问 I有上面作为一个xvalue,)

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

如果值类别不能确定右值的生命周期何时会延长,那该怎么办?当右值的生命周期在 C++ 中延长时,我很难理解

4

2 回答 2

5

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

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

重点补充。

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

决定临时是否扩展的正是上述(以及更多规则)。


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

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

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

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

函数做什么、说什么或暗示什么并不重要。编译器是否可以内联并确定返回值是对来自临时参数的引用并不重要。该临时的生命周期是固定的表达式,而不是延长。

于 2017-02-24T15:02:08.483 回答
1

如果值类别不能确定右值的生命周期何时会延长,那该怎么办?当右值的生命周期在 C++ 中延长时,我很难理解

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

来自 n4296 标准草案:

  • §12.2.1

    类类型的临时对象是在各种上下文中创建的:将引用绑定到纯右值 (8.5.3)、返回纯右值 (6.6.3)、创建纯右值的转换 (4.1、5.2.9、5.2.11、5.4) ,抛出异常(15.1),并在一些初始化(8.5)。

  • §12.2.4

    有两种情况,其中临时对象在与完整表达式结尾不同的点被销毁。[...]
    第二个上下文是引用绑定到临时. 引用绑定到的临时对象或作为引用绑定到的子对象的完整对象的临时对象在引用的生命周期内持续存在

注意:我没有引用第一个上下文,因为它对这些问题有轻微的启示。我添加的斜体强调。

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


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

于 2017-02-24T15:23:00.313 回答