为什么命名引用是左值?

时间:2019-05-26 19:35:04

标签: c++ rvalue-reference value-categories

我知道命名的引用是左值:

int x = 1;
int& ref1 = x;
int&& ref2 = std::move(x);

我已经阅读了说明-这是因为我们可以使用那些ref1ref2的地址。

但是当我们获取引用的地址时,实际上是获取被引用对象的地址,不是吗?因此,这种解释似乎不正确。

那为什么命名引用是左值?

3 个答案:

答案 0 :(得分:3)

每个[expr.prim.id.unqual](8.1.4.1不合格名称):

  

[...]如果实体是函数,则表达式为左值,   变量或数据成员,否则为prvalue;如果是位场   标识符指定一个位字段([dcl.struct.bind])。

[basic]/6

  

变量 通过引用其他变量的声明引入   而不是非静态数据成员或对象。变量的名称,如果   任何,表示引用或对象。

声明

int&& ref2 = std::move(x);

是“对非静态数据成员以外的引用的声明”。因此,由ref2表示的实体是变量。因此,表达式ref2是一个左值。

答案 1 :(得分:2)

这种解释只是一种简化。左值不是通过“您可以接受的地址”来定义的,而是通过关于表达式的值类别的一组特定规则来定义的。这些规则经过精心构造,以形成一种自统一的语言,使所有内容都合理整齐地融合在一起。

话虽这么说,解释在这里比较合适,如果您认为通过编写ref1来表示,则不是真正地命名“引用”,而是要引用的东西。那就是引用的魔力:您应该考虑给它们命名别名,而不是按其本身的名称命名。

围绕它有一些抽象泄漏(尤其是成员引用),但这就是要点。

您应该忘记“引用是左值”之类的概念,而应该考虑表达式。对象具有类型;表达式具有值类别。

答案 2 :(得分:-1)

这是斯科特·迈耶斯(Scott Meyers)的著作《有效的现代C ++》的解释:

  

实际上,Reject H0 is |t|>t_(alpha/2) 有两种不同的含义。当然,一种是右值引用。此类引用的行为完全符合您的期望:它们仅绑定到右值,并且它们的主要 raison d'être用于标识可能从中移出的对象。

T&&
     

void f(Widget&& param); // rvalue reference Widget&& var1 = Widget(); // rvalue reference auto&& var2 = var1; // not rvalue reference template<typename T> void f(std::vector<T>&& param); // rvalue reference template<typename T> void f(T&& param); // not rvalue reference 的其他含义是右值引用或左值引用。这样的引用看起来像源代码中的右值引用(即T&&),但是它们的行为就像是左值引用(即T&&)一样。它们的双重性质使它们可以绑定到右值(如右值引用)以及左值(如左值引用)。此外,它们可以绑定到T&或非const对象,const或非volatile对象,甚至绑定到volatile和{ {1}}。它们几乎可以绑定任何东西。这种空前灵活的参考文献应有自己的名字。我称它们为通用参考。