xvalues vs prvalues:标识属性添加了什么

时间:2017-07-26 04:56:03

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

我很抱歉问题的广泛性,只是所有这些细节紧密相连......

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

无论如何,我试图为自己开发的“身份”概念的心理模型是,应该保证具有它的表达式驻留在实际程序的数据存储器中。

由于这个原因,字符串文字是左值,它们保证在整个程序运行中驻留在内存中,而数字文字是prvalues,例如可以假设存储在直接asm中。

同样似乎适用于来自prvalue文字的std::move,即在调用fun(1)时,我们只会在被调用者帧中获得参数lvalue,但在调用fun(std::move(1)) xvalue'类时'glvalue'必须保留在调用者框架中。

然而,这个心智模型至少对临时对象不起作用,据我所知,临时对象应该始终在实际内存中创建(例如,如果调用rvalue-ref-taking func,如fun(MyClass())一个prvalue论点)。所以我猜这种心理模型是错误的。

那么考虑xvalues的'identity'属性的正确方法是什么?我已经阅读了有身份我可以比较地址,但如果我可以比较2 MyClass().member s的地址(xvalue根据cppreference),让我们说通过rvalue refs传递给某些比较函数,然后我不明白为什么我不能用2 MyClass() s(prvalue)做同样的事情?

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

  

请注意,即使std :: move(a)是rvalue,其评估也不会创建临时对象。这个难题迫使委员会引入第三个价值类别。可以绑定到右值引用的东西,即使它不是传统意义上的右值,也称为x值(eXpiring值)。

但这似乎与'可以比较地址'和a)无关。我不知道这与rvalue的'传统意义'有什么不同; b)我不明白为什么这样的理由需要语言中的新值类别(好吧,好吧,这允许为OO意义上的对象提供动态类型,但xvalues不仅仅引用对象)。

2 个答案:

答案 0 :(得分:3)

我个人有另一种心理模型,它并不直接处理身份和记忆等等。

prvalue来自"纯右价"而xvalue来自"到期值"这是我在心智模型中使用的这些信息:

纯rvalue 指的是一个临时的纯粹意义上的对象":一个表达式,编译器可以绝对肯定地告诉它,它的评估是一个对象,是一个临时的,刚刚创建并且即将到期(除非我们通过引用绑定进行干预以延长它的生命周期)。该对象是在表达式的评估过程中创建的,它将根据"母亲表达的规则而死亡。

相比之下,到期值是一个表达式,其计算结果是对承诺即将到期的对象的引用。这就是它给了你一个承诺,你可以对这个对象做任何你想做的事,因为它无论如何都会被破坏。但是你不知道这个对象什么时候被创建,或者什么时候应该被销毁。你只知道你被拦截了#34;因为它即将死去。

在实践中:

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();

这不会延长寿命。

答案 1 :(得分:0)

当呼叫func(T&& t)时,呼叫者说“这里有一个”,还有“我不在乎你对它做了什么”。 C ++没有指定“here”的性质。

在将参考参数实现为地址的平台上,这意味着必须存在某个对象。在该平台上标识==地址。但是,这不是语言的要求,而是平台调用约定的要求。

平台可以简单地通过在呼叫者和被呼叫者中以特定方式安排要注册的对象来实现引用。这里的身份可以是“注册edi”。