我知道命名的引用是左值:
int x = 1;
int& ref1 = x;
int&& ref2 = std::move(x);
我已经阅读了说明-这是因为我们可以使用那些ref1
和ref2
的地址。
但是当我们获取引用的地址时,实际上是获取被引用对象的地址,不是吗?因此,这种解释似乎不正确。
那为什么命名引用是左值?
答案 0 :(得分:3)
每个[expr.prim.id.unqual](8.1.4.1不合格名称):
[...]如果实体是函数,则表达式为左值, 变量或数据成员,否则为prvalue;如果是位场 标识符指定一个位字段([dcl.struct.bind])。
变量 通过引用其他变量的声明引入 而不是非静态数据成员或对象。变量的名称,如果 任何,表示引用或对象。
声明
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}}。它们几乎可以绑定任何东西。这种空前灵活的参考文献应有自己的名字。我称它们为通用参考。