c++ - xvalues 与 prvalues : what does identity property add

标签 c++ c++14 xvalue value-categories prvalue

对于这个问题的广泛性,我很抱歉,只是所有这些细节都是紧密相关的..

我一直在努力理解具体两个值类别(xvalues 和 prvalues)之间的区别,但我仍然感到困惑。

无论如何,我试图为自己建立的关于“身份”概念的心智模型是,应该保证拥有它的表达式驻留在实际程序的数据内存中。

正因如此,字符串字面量是左值,它们保证在整个程序运行期间驻留在内存中,而数字字面量是纯右值,例如假设存储在直接 asm 中。

这似乎也适用于纯右值文字中的 std::move,即当调用 fun(1) 时,我们只会获得被调用方帧中的参数左值,但是当调用 fun(std::move(1)) 时,glvalue 的 xvalue 'kind' 必须保存在调用者框架中。

然而,这种心智模型至少不适用于临时对象,据我所知,临时对象应该始终在实际内存中创建(例如,如果一个右值引用函数被称为 fun(MyClass ()) 带有纯右值参数)。所以我猜这个心智模型是错误的。

那么思考 xvalues 的“身份”属性的正确方法是什么?我已经读过,通过身份我可以比较地址,但是如果我可以比较 2 个 MyClass().member 的地址(根据 cppreference 的 xvalue),假设通过右值引用将它们传递给一些比较函数,那么我不明白为什么我不能用 2 个 MyClass()s (prvalue) 做同样的事情?

与此相关的另一个来源是此处的答案: What are move semantics?

Note that even though std::move(a) is an rvalue, its evaluation does not create a temporary object. This conundrum forced the committee to introduce a third value category. Something that can be bound to an rvalue reference, even though it is not an rvalue in the traditional sense, is called an xvalue (eXpiring value).

但这似乎与“可以比较地址”无关,并且 a) 我看不出这与右值的“传统意义”有何不同; b) 我不明白为什么这样的原因需要语言中的新值类别(好吧,好吧,这允许为 OO 意义上的对象提供动态类型,但 xvalues 不仅仅指对象)。

最佳答案

我个人有另一种心智模型,它不直接处理身份和内存等等。

prvalue 来自“pure rvalue”,而 xvalue 来自“expiring value”,这是我在心智模型中使用的信息:

纯右值指的是“纯粹意义上”的临时对象:编译器可以绝对确定地判断其求值是一个具有以下临时性的对象的表达式刚刚创建并且即将过期(除非我们通过引用绑定(bind)进行干预以延长其生命周期)。该对象是在表达式求值期间创建的,它将根据“母表达式”的规则消亡。

相比之下,过期值 是一个表达式,其计算结果为对 promise 即将过期的对象的引用。那就是它给了你一个 promise ,你可以对这个对象做任何你想做的事,因为无论如何它接下来都会被销毁。但是你不知道这个对象是什么时候创建的,或者它应该在什么时候被销毁。你只知道你“拦截”了它,因为它快要死了。

实践中:

struct X;
auto foo() -> X;
X x = foo();
      ^~~~~

在此示例中,计算 foo() 将产生一个 prvalue。只要查看这个表达式,您就会知道这个对象是作为 foo 返回的一部分创建的,并将在这个完整表达式的末尾被销毁。因为您知道所有这些事情,所以您可以开启它的生命周期:

const X& rx = foo();

现在 foo 返回的对象的生命周期延长到 rx

auto bar() -> X&&
X x = bar();
      ^~~~

在此示例中,计算 bar() 将产生一个 xvaluebar 向您保证 给您一个即将过期的对象,但您不知道这个对象是什么时候创建的。它可以在调用 bar 之前创建(无论是否是临时的),然后 bar 为您提供对它的 rvalue reference。优点是你知道你可以用它做任何你想做的事,因为它不会在后记中使用(例如,你可以从它移动)。但是你不知道这个对象什么时候应该被销毁。因此你不能延长它的生命周期——因为你一开始就不知道它原来的生命周期是多少:

const X& rx = bar();

这不会延长生命周期。

关于c++ - xvalues 与 prvalues : what does identity property add,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45317763/

相关文章:

c++ - 为什么使用稍后定义的另一个常量变量将表达式限定为非常量表达式

c++ - 竞争条件效应

c++ - 用于检测 Ajax 调用的 Internet Explorer 插件

python - Cython 是否支持 C++11 容器?

c++ - 将重载函数转换为专用函数模板

c++ - 使用 C++ 将越南语字符从 ISO88591、UTF8、UTF16BE、UTF16LE、UTF16 编码为十六进制,反之亦然

c++ - 为什么函数调用是一个 xvalue(如果返回类型是一个右值)?

c++ - 成员函数返回成员变量的右值引用

c++ - 5 与 std::move(5) 的行为差异

c++ - 在 Qt Creator 中使用 C++11