本文介绍了右值,左值和形式定义的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

人们在

int&& x

x具有右值引用类型,但是x是左值.误解源于标识符和表达式是不同的事物,类型和值类别也是不同的事实.此外,表达式的类型在进行任何进一步分析之前已进行了调整",并且单词"rvalue"和"lvalue"可以同时出现在类型名称和值类别名称中.

x has rvalue reference type, but x is an lvalue. Misunderstanding stems from the fact that identifiers and expressions are different things, and so are types and value categories. Moreover, types of expressions are "adjusted prior to any further analysis", and the words "rvalue" and "lvalue" can appear both in type name and in value category name.

我想澄清正式定义.假设我们有一个函数:

I want to clarify formal definitions. Suppose we have a function:

1 | void f(int&& x) {
2 |     ... = x;
3 |     ... = std::move(x);
4 | }

以下陈述正确吗?

  1. 在第1行中,x是用于命名函数参数的标识符(id-expression).它的类型是int&&,这是decltype(x)返回的类型. x不是表达式,没有值类别.
  2. 在第2行中,x是一个表达式.在类型调整之前,其类型为int&&,在类型变为int之后.值类别为左值.
  3. 在第3行中,std::move(x)是一个表达式.调整之前的类型为int&&,之后为-int.值类别为xvalue.
  4. 当我们说x具有右值引用类型时,我们将x的类型称为标识符,或者将x的类型称为表达式,然后进行类型调整.
  5. 声明每个表达式都有一些非引用类型,每个表达式恰好属于三个主要值类别之一"中的语句,位于 cppreference.com 指的是类型调整后的类型.
  6. 当Scott Meyers 写入时,如果表达式的类型是左值引用(例如T&const T&等),则该表达式是左值."他是指调整前的类型,第二个单词左值"是指值类别.
  1. In the line 1, x is an identifier (id-expression) that names a function parameter. Its type is int&&, and this is the type that decltype(x) returns. x is not an expression and has no value category.
  2. In the line 2, x is an expression. Before type adjustment its type is int&&, and after the type becomes int. The value category is lvalue.
  3. In the line 3, std::move(x) is an expression. Its type before adjustment is int&&, after - int. The value category is xvalue.
  4. When we say that x has rvalue reference type, we refer either to the type of x as an identifier, or to the type of x as an expression before type adjustment.
  5. The word "type" in the statement "Each expression has some non-reference type, and each expression belongs to exactly one of the three primary value categories" at cppreference.com refers to the type after type adjustment.
  6. When Scott Meyers writes "If the type of an expression is an lvalue reference (e.g., T& or const T&, etc.), that expression is an lvalue." he refers to the type before adjustment, and the second word "lvalue" refers to the value category.

推荐答案

首先是一些初步段落:

3 实体是值,对象,引用,函数,枚举器, 类型,类成员,模板,模板专业化,名称空间, 参数包或这个.

3 An entity is a value, object, reference, function, enumerator, type, class member, template, template specialization, namespace, parameter pack, or this.

[dcl.type.simple]

4 由的定义如下:

4 The type denoted by decltype(e) is defined as follows:

  • 如果e是未括号的 id-expression 或未括号的类成员访问权限([expr.ref]),则decltype(e)e命名的实体.如果没有这样的实体,或者e命名一个集合 的重载函数,程序格式错误;

  • if e is an unparenthesized id-expression or an unparenthesized class member access ([expr.ref]), decltype(e) is the type of the entity named by e. If there is no such entity, or if e names a set of overloaded functions, the program is ill-formed;

否则,如果e是xvalue,则decltype(e)T&&,其中Te的类型;

otherwise, if e is an xvalue, decltype(e) is T&&, where T is the type of e;

否则,如果e是左值,则decltype(e)T&,其中Te的类型;

otherwise, if e is an lvalue, decltype(e) is T&, where T is the type of e;

否则,decltype(e)e的类型.

[dcl.ref]

1 在声明T D中,其中D具有以下两种形式之一

1 In a declaration T D where D has either of the forms


& attribute-specifier-seq D1
&& attribute-specifier-seq D1

,声明T D1中的标识符类型为 " derived-declarator-type-list T",然后是标识符的类型 D的是对T派生声明器类型列表引用."

and the type of the identifier in the declaration T D1 is "derived-declarator-type-list T," then the type of the identifier of D is "derived-declarator-type-list reference to T."

[expr]

5 如果表达式最初的类型为对T" ([dcl.ref],[dcl.init.ref]),将类型先调整为T 更深入的分析.表达式指定对象或功能 由参考表示,并且表达式是左值或 xvalue,具体取决于表达式.

5 If an expression initially has the type "reference to T" ([dcl.ref], [dcl.init.ref]), the type is adjusted to T prior to any further analysis. The expression designates the object or function denoted by the reference, and the expression is an lvalue or an xvalue, depending on the expression.

[expr.prim.general]

8 一个标识符 id-expression ,只要已适当 声明(条款[dcl.dcl]).表达式的类型是 标识符.结果是由标识符表示的实体. 如果实体是函数,变量或数据,则结果为左值 成员,否则为prvalue.

8 An identifier is an id-expression provided it has been suitably declared (Clause [dcl.dcl]). The type of the expression is the type of the identifier. The result is the entity denoted by the identifier. The result is an lvalue if the entity is a function, variable, or data member and a prvalue otherwise.

[expr.call]

10 如果函数调用是左值结果类型是左值 引用类型或对函数类型的右值引用,如果为xvalue 结果类型是对对象类型的右值引用和prvalue 否则.

10 A function call is an lvalue if the result type is an lvalue reference type or an rvalue reference to function type, an xvalue if the result type is an rvalue reference to object type, and a prvalue otherwise.

现在允许我们回答您的问题.

Which now allows us to answer your questions.

是的.声明中的x不是表达式.但是,作为decltype 的一个参数,是一个表达式.但是,它遇到了decltype的第一个项目符号的特殊情况,因此推导了以x命名的标识符的类型,而不是作为表达式的x的类型.

Yes of sorts. x in the declaration is not an expression. But as an argument to decltype is an expression. However, it hits the special case of decltype's first bullet so the type of the identifier named by x is deduced, instead of the type of x as an expression.

是的

是的

是的

是的

不能确切地说出斯科特·迈耶斯(Scott Meyers)在写这篇文章时的意思,但这是对与标准相符的单词的唯一解释,是的.

Can't really say for sure what Scott Meyers meant when he wrote this, but that is the only interpretation of the words that matches up with the standard, yes.

这篇关于右值,左值和形式定义的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-24 16:45