我对这个问题的广泛性感到抱歉,只是所有这些细节都是紧密相连的。
我一直试图理解两个具体的值类别-xvalue和prvalue之间的区别,但我仍然感到困惑。
无论如何,我试图为“身份”的概念为自己开发的心理模型是,拥有它的表达式应该保证驻留在实际程序的数据内存中。
与此类似,字符串文本是lvalue,它们保证驻留在整个程序运行的内存中,而数字文本是prvalue,可以假设存储在直接的asm中。
这似乎也适用于来自prvalue文字的std::move,即当调用fun(1)时,我们只会在被调用的帧中获得参数lvalue,但是当调用fun(std::move(1))时,xvalue的“类”值必须保持在调用方帧中。
然而,这个心智模型至少对临时对象不起作用,据我所知,这些对象应该总是在实际内存中创建(例如,如果rvalue-ref-taking被称为带有prvalue参数的fun(MyClass()) )。所以我想这个心理模型是错误的。
那么,如何正确地考虑xvalue的“标识”属性呢?我已经读过,通过标识,我可以比较地址,但是如果我可以比较2 MyClass().members的地址(根据cppreference),那么让我们假设,通过将它们传递给某些比较函数,那么我不明白为什么不能对2 MyClass()s (prvalue)做同样的比较。
与此相关的另一个来源是这里的答案:What are move semantics?
注意,即使std::move(a)是一个rvalue,它的计算结果也不会创建一个临时对象。这个难题迫使委员会引入了第三个价值类别。可以绑定到rvalue引用的东西,即使它不是传统意义上的rvalue,也称为xvalue (eXpiring值)。
但这似乎与“可以比较地址”和( a)我看不出这与rvalue的“传统意义”有何不同;( b)我不明白为什么这样的原因需要在语言中建立一个新的值类别(好吧,这允许为OO意义上的对象提供动态类型,但xvalue不仅仅指对象)。
发布于 2017-07-26 09:43:30
我个人有另一个心理模型,它不直接处理身份和记忆之类的问题。
prvalue来自“纯rvalue”,而xvalue来自“过期值”,这是我在心智模型中使用的信息:
Pure rvalue指的是一个“纯意义上的临时对象”:一个表达式,编译器可以绝对肯定地判断它的计算值是一个临时的、刚刚创建的并且是立即过期的对象(除非我们进行干预,通过引用绑定来延长它的生存期)。对象是在对表达式的评估过程中创建的,它将按照“母表达式”的规则死亡。
相反,到期值是一个表达式,它的计算结果是对即将过期的对象的引用。也就是说,它给了你一个承诺,你可以对这个物体做任何你想做的事情,因为它将被摧毁。但是您不知道这个对象是什么时候创建的,也不知道什么时候应该销毁它。你只知道你“拦截”了它就快死了。
在实践中:
struct X;
auto foo() -> X;X x = foo();
^~~~~在本例中,计算foo()将导致prvalue。通过查看这个表达式,您就知道这个对象是作为foo返回的一部分创建的,并将在这个完整表达式的末尾销毁。因为你知道所有这些事情,你可以开场白,这是一生的事:
const X& rx = foo();现在foo返回的对象将它的生存期延长到rx的生存期
auto bar() -> X&&X x = bar();
^~~~在本例中,计算bar()将导致xvalue。bar承诺给您一个即将过期的对象,但是您不知道这个对象是什么时候创建的。可以在调用bar之前(作为临时的或非临时的)创建它,然后bar为它提供一个rvalue reference。优点是你知道你可以用它做任何你想做的事,因为它不会被使用(例如,你可以从它移开)。但你不知道什么时候这个物体应该被摧毁。因此,您不能扩展它的生存期--因为您不知道它最初的生命周期是什么:
const X& rx = bar();这不会延长你的寿命。
发布于 2017-07-26 08:45:12
当调用func(T&& t)时,调用者在说“这里有一个t”,并且“我不在乎您对它做了什么”。C++没有指定“这里”的性质。
在一个将引用参数实现为地址的平台上,这意味着一定有一个对象存在于某个地方。在那个平台上标识==地址。然而,这不是语言的要求,而是平台调用约定的要求。
平台可以通过安排调用方和被调用方以特定方式注册对象来实现引用。在这里,身份可以是“注册edi”。
https://stackoverflow.com/questions/45317763
复制相似问题