为什么C++(11) 中没有 Rconst int
值?我认为 R 值是不能在左侧的“任何东西”,而常量可以满足这一点。此代码失败:
int f(int && x) { return 100; }
void g() {
const int x = 1;
f(x);
}
error: invalid initialization of reference of type ‘int&&’ from expression
of type ‘const int’
好的,表达式1分为三类:
第一个被称为左值,第二个是xvalues,第三个是prvalues。如果我们将左值和 xvalues 放在一起,我们就有了 glvalues。Glvalues 是所有表示具有标识的对象的表达式。如果我们将 xvalues 和 prvalues 放在一起,我们就有 rvalues。右值是表示可以移动的对象的所有表达式。
有问题的表达式x
, 是一个glvalue:可以写&x
,所以对象显然有一个标识。
我们可以从这个表达式中移开吗?这个对象即将过期吗?不它不是。它仅在当前表达式之后的某个时间过期。这意味着它不能被移动。这使它成为一个左值。
所有这些名称可能有点令人困惑,因为 C++ 中的左值和右值不再意味着它们在 C 起源中的含义。C++ 的含义与在 assignment 2的左侧或右侧完全无关。
就个人而言,我更喜欢使用Bjarne这篇论文中的术语:iM-values(而不是 lvalues)、im-values(而不是 xvalues)、Im-values(而不是 prvalues)、i-values(而不是 glvalues)、和 m 值(而不是右值)。不幸的是,这不是标准使用的术语。
1这里的“有身份”是指“可以取其地址”;“可以移出”意味着它即将到期,要么是由于它的临时性质,要么是因为程序员通过调用std::move
或类似的东西在类型系统中明确表示了这一点。
2你可以在赋值的左边有右值:std::vector<int>(17) = std::vector<int>(42)
是一个有效的表达式,即使它是无用的。
我认为 R 值是“任何东西”,不能在 [赋值操作] 的左侧
那是 C++03 的定义rvalue
,即便如此,它也是一种俗语,并非普遍适用。
在 C++11 中, 和 的定义lvalue
有所rvalue
改变。规则很复杂,标准中的个别情况会根据具体情况进行处理,但这里有一个一般的经验法则:
lvalue
lvalue
引用,则该表达式是lvalue
rvalue
在您的特定情况下,您可以获取x
(例如,它“有名字”)的地址,因此它是一个左值。
您可以在两篇优秀的文章中阅读更多关于 C++11 中左值和右值的信息:
参数类型是右值引用,标准禁止使用“引用相关”类型的左值初始化右值引用。
8.5.3 参考文献[dcl.init.ref]
...
5 ... 如果 T1 与 T2 引用相关并且引用是右值引用,则初始化表达式不应是左值。
因此,以下是错误:
void f (long &&);
const long x = 1;
void g () { f (x); }
但以下不是:
void f (long &&);
const int x = 1;
void g () { f (x); }
因此,错误的原因不仅仅是“初始化不是使用右值”,而是因为“初始化是使用与引用相关类型的左值”。
简单来说,您应该能够“窃取”右值的值。这是对右值进行不同处理的重点。所以右值应该是未命名的,即将在不久的将来死去的东西。