18

前提:

C++11 标准将表达式分为三个不相交的值类别lvaluesxvaluesprvalues (§ 3.10/1)。例如,此处提供了有关哪些值类别的说明。

我正在努力弄清楚不同运算符对其操作数的值类别的要求是什么。第 3.10/1 段规定:

[...] 每个表达式都属于该分类法中的基本分类之一:左值、xvalue 或 prvalue。表达式的这个属性称为它的值类别。[注意:第 5 章中对每个内置运算符的讨论表明了它产生的值的类别以及它所期望的操作数的值类别。例如,内置赋值运算符期望左操作数是左值,右操作数是纯右值并产生左值作为结果。用户定义的运算符是函数,它们期望和产生的值的类别由它们的参数和返回类型决定。——尾注]

尽管上面的注释声称,第 5 条并不总是很清楚运算符操作数的值类别。例如,这就是关于赋值运算符的操作数的值类别的所有内容(第 5.17/1 段):

赋值运算符 (=) 和复合赋值运算符都从右到左分组。所有这些都需要一个可修改的左值作为它们的左操作数,并返回一个指向左操作数的左值。如果左操作数是位域,则所有情况下的结果都是位域。在所有情况下,赋值都在左右操作数的值计算之后和赋值表达式的值计算之前进行排序。对于不确定顺序的函数调用,复合赋值的操作是单次求值。[注意:因此,函数调用不应干预左值到右值的转换以及与任何单个复合赋值运算符相关的副作用。——尾注]

正确的操作数怎么样?

整个 5.17 节中不再出现“rvalue”和“lvalue”这两个词。虽然第 3.10/1 段中的注释明确指出内置赋值运算符期望纯右值作为右操作数,但在第 5.17 节中并未明确提及。即使是 5.17/1 的最后一个注释,它提到了左值到右值的转换,似乎也暗示了右值是以某种方式被预期的(否则需要什么转换?),但注释毕竟是非规范的。

有关其他运算符的部分,包括乘法和加法运算符,通常对其操作数的值类别保持沉默。我在标准中找不到任何“默认语句”指出,如果未另行指定,内置运算符的操作数是右值。因此,问题。

问题:

  1. 赋值运算符的右操作数的值类别是什么;而且,更一般地说
  2. 未指定时如何确定运算符操作数的值类别?是否不受约束(意味着接受任何值类别)?如果是这样,为什么左值到右值的转换应该应用于赋值表达式?

高度赞赏对 C++11 标准的引用。

4

1 回答 1

7

是的,它没有详细说明,之前已经介绍过。基本上,每次需要左值表达式时都会枚举,因此我们假设每个其他操作数都必须是纯右值表达式。

所以回答你的问题:

  1. 一个prvalue。
  2. 如果未指定,则为prvalue。

链接答案中引用的注释似乎已经更改了几次。C++11 标准第 3.10 节的引用如下(目前在最新草案中是相同的):

[ 注意:第 5 章中对每个内置运算符的讨论表明了它产生的值的类别以及它所期望的操作数的值类别。例如,内置赋值运算符期望左操作数是左值,右操作数是纯右值并产生左值作为结果。用户定义的运算符是函数,它们期望和产生的值的类别由它们的参数和返回类型决定。——尾注]

这里甚至明确表示赋值运算符期望正确的操作数是纯右值。当然,这是一个注释,因此是非规范性的。

于 2013-02-20T22:39:38.530 回答