xvalues是否具有标识并可移动?

7
根据这份文件:

http://www.stroustrup.com/terminology.pdf

  1. l-values具有身份并且不可移动。
  2. pr-values是可移动的但没有身份。
  3. x-values具有身份并且可移动。

我有几个关于这些的问题。

a. x-value具有身份的例子是什么?以下内容是不合法的:

Foo f;
&std::move(f);
b. 我可以重载类Foo的&运算符,并使其返回this,以便以下内容合法:
&Foo(5);

但是像Foo(5)这样的pr值不能具有身份。或者有更微妙的身份解释吗?


4
xvalue通常是将对象转换为右值引用或访问xvalue类对象的成员的结果。例如,auto x = 42; static_cast<int&&>(x),这个static_cast的结果就是一个xvalue。 - dyp
1
你读过标准中关于值类别的正式规范吗?我对“具有身份”原则也有些困惑(有些人将其用作“对象”的定义),但标准似乎并未使用它。 - dyp
2个回答

6
以下是 Stroutrup 的《C++ 程序设计语言》中的内容,可能会解决这个问题:
void f(vector<string>& vs)
{
vector<string>& v2 = std::move(vs);// move vs to v2
// ...
}

Here, std::move(vs) is an xvalue: it
clearly has identity (we can refer to
it as vs), but we have explicitly given
permission for it to be moved from by
calling std::move() 3.3.2, §35.5.1).
For practical programming, thinking in
terms of rvalue and lvalue is usually 
sufficient. 

5
或者,对于 identity 还有更微妙的解释吗?
您链接的文档包含以下两个定义:
“具有 identity” - 即地址、指针、用户可以确定两个副本是否相同等。
“可移动”- 即我们可以将“复制品”的源留在某些不确定但有效的状态中。
查看标准后,我们可以得出 “对象” 的定义(见 §1.8/1):
对象是存储区域。
根据 §1.7/1 规定:
每个字节都有唯一的地址。
这意味着定义非常广泛,并且包括几乎每种类型值的每个对象(rvalue、xvalue、prvalue、lvalue 等)。
什么是 x-value 具有 identity 的示例?
标准本身给出了生成 xvalue 的表达式列表(见 §5/7):
如果以下条件之一成立,则表达式是 xvalue: - 调用返回对象类型的 rvalue 引用的函数的结果(无论是否隐式调用); - 强制转换为对象类型的 rvalue 引用; - 指定非引用类型的非静态数据成员的类成员访问表达式,其中对象表达式是 xvalue; - 第一个操作数是 xvalue,第二个操作数是指向数据成员的指针的 .* 成员指针表达式。
总体上,此规则的效果是命名的 rval 引用被视为 lvalue,未命名的对象 rval 引用被视为 xvalue;函数 rval 引用被视为 lvalue,无论其是否命名。
随后给出了一些示例。以下是其中的几个扩展:
struct A { int m; };

A&& operator+(A, A);
A a;
A b;
a + b;   // xvalue

A&& f();
f();     // xvalue
f().m;   // xvalue

A a;
static_cast<A&&>(a);  // xvalue
std::move(a);         // xvalue

3
x值表达式的身份是什么?如何获取它?表达式std::move(a)的身份(或地址)是什么?我想它应该是&a。但我们无法对其应用&运算符。这与一个pr值有何不同?或者是因为一个名称绑定到底层对象,而x值表达式使得从中移动变得可能。 - CppNoob
1
@ArindamMukherjee:这是一个有趣的问题。我不确定不允许xvalue的地址背后的理由,但我怀疑这只是为了避免错误。在实践中,xvalues相当罕见,因此没有太多理由使获取它们的地址变得非常方便。但是,xvalue将转换为const lvalue引用,然后您可以获取所引用对象的地址。 - Vaughn Cato
2
@ArindamMukherjee: 这仍然引发了关于“identity”的问题,因为您也可以将const引用绑定到prvalue上。似乎区别在于是否涉及临时对象。因此,一旦引用绑定到临时对象上并且可以获取其地址,那么临时对象就变成了非临时对象吗?我想这是一种看待它的方式。 - Vaughn Cato

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接