简体   繁体   English

为什么命名右值引用是左值表达式?

[英]Why is a named rvalue reference an lvalue expression?

I know that a named reference is an lvalue:我知道命名引用是左值:

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

I've read the explanation — that is because we can take the address of those ref1 and ref2 .我已经阅读了解释——那是因为我们可以获取那些ref1ref2的地址。

But when we take the address of a reference we actually take the address of the referenced object, don't we?但是当我们取一个引用的地址时,我们实际上取的是被引用的 object 的地址,不是吗? So this explanation doesn't seem to be correct.所以这个解释似乎并不正确。

So why a named reference is an lvalue?那么为什么命名引用是左值呢?

Per [expr.prim.id.unqual] (8.1.4.1 Unqualified names): Per [expr.prim.id.unqual] (8.1.4.1非限定名称):

[...] The expression is an lvalue if the entity is a function, variable, or data member and a prvalue otherwise; [...]如果实体是函数,变量或数据成员,则表达式是左值;否则为prvalue; it is a bit-field if the identifier designates a bit-field ([dcl.struct.bind]). 如果标识符指定位字段([dcl.struct.bind]),则它是位字段。

Per [basic]/6 : [基本] / 6

A variable is introduced by the declaration of a reference other than a non-static data member or of an object. 通过声明除非静态数据成员或对象之外的引用引入变量 The variable's name, if any, denotes the reference or object. 变量的名称(如果有)表示引用或对象。

The declaration 声明

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

is a "declaration of a reference other than a non-static data member." 是“非静态数据成员之外的引用声明”。 Therefore, the entity denoted by ref2 is a variable. 因此, ref2表示的实体是变量。 So the expression ref2 is an lvalue. 所以表达式ref2是一个左值。

That explanation is just a simplification. 这种解释只是一种简化。 lvalues aren't defined by being "something you can take the address of", but by a specific set of rules about the value category of expressions. 左值不是通过“你可以获取地址的东西”来定义的,而是通过关于表达式的值类别的一组特定规则来定义的。 Those rules are carefully constructed so as to result in a self-consistent language in which everything fits together reasonably neatly. 这些规则是经过精心构建的,以便形成一种自洽的语言,在这种语言中,所有东西都能合理地整齐地组合在一起。

That being said, the explanation does rather fit here, if you consider that by writing ref1 , you're not really naming "the reference" but the thing being referred to. 话虽这么说,解释确实适合这里,如果你考虑通过编写ref1 ,你不是真的命名“引用”而是引用的东西。 That's the magic of references: you're supposed to consider them name aliases rather than entities in their own right. 这是引用的魔力:你应该把它们视为名称别名而不是它们自己的实体。

There are some abstraction leaks surrounding this (particularly, member references), but that's the gist. 围绕这个有一些抽象泄漏(特别是成员引用),但这就是要点。

You ought to forget about notions like "the reference is an lvalue" and instead think about expressions . 你应该忘记像“引用是左值”这样的概念,而是考虑表达式 Objects have types; 物体有类型; expressions have value categories. 表达式具有值类别。

Here is an explanation from Scott Meyers's book "Effective Modern C++": 以下是Scott Meyers的书“Effective Modern C ++”的解释:

In fact, T&& has two different meanings. 事实上, T&&有两种不同的含义。 One is rvalue reference, of course. 一个是右值参考,当然。 Such references behave exactly the way you expect: they bind only to rvalues, and their primary raison d'être is to identify objects that may be moved from. 这些引用的行为与您期望的完全相同:它们只与rvalues绑定,它们的主要存在理由是识别可能被移动的对象。

 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 

The other meaning for T&& is either rvalue reference or lvalue reference. T&&的另一个含义是右值引用或左值引用。 Such references look like rvalue references in the source code (ie, T&& ), but they can behave as if they were lvalue references (ie, T& ). 这些引用看起来像源代码中的右值引用(即T&& ),但它们的行为就像它们是左值引用(即T& )。 Their dual nature permits them to bind to rvalues (like rvalue references) as well as lvalues (like lvalue references). 它们的双重性质允许它们绑定到rvalues(如rvalue引用)以及lvalues(如左值引用)。 Furthermore, they can bind to const or non- const objects, to volatile or non- volatile objects, even to objects that are both const and volatile . 此外,它们可以结合于const或非const物体, volatile或非易失volatile物体,甚至是两个对象constvolatile They can bind to virtually anything. 它们几乎可以绑定任何东西。 Such unprecedentedly flexible references deserve a name of their own. 这种前所未有的灵活参考应该得到自己的名字。 I call them universal references. 我称之为普遍参考。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM