【发布时间】:2013-02-06 03:00:25
【问题描述】:
前提:
C++11 标准将表达式分为三个不相交的值类别:lvalues、xvalues和prvalues(第 3.10/1 节)。例如,here 提供了对哪些值类别的说明。
我正在努力弄清楚不同运算符对其操作数的值类别的要求是什么。第 3.10/1 段规定:
[...] 每个表达式都属于该分类法中的基本分类之一:左值、xvalue 或 prvalue。表达式的这个属性称为它的值类别。 [ 注意:第 5 条中对每个内置运算符的讨论表明了它产生的值的类别以及它所期望的操作数的值类别。例如,内置赋值运算符期望左操作数是左值,右操作数是纯右值并产生左值作为结果。用户定义的运算符是函数,它们期望和产生的值的类别由它们的参数和返回类型决定。 ——尾注]
尽管上面的注释声称,第 5 条并不总是很清楚运算符操作数的值类别。例如,这就是关于 assignment 运算符的操作数的值类别的所有内容(第 5.17/1 段):
赋值运算符 (=) 和复合赋值运算符都从右到左分组。 都需要一个可修改的左值作为其左操作数,并返回一个引用左操作数的左值。如果左操作数是位域,则所有情况下的结果都是位域。在所有情况下,赋值都在左右操作数的值计算之后和赋值表达式的值计算之前进行排序。对于不确定顺序的函数调用,复合赋值的操作是单次求值。 [注意:因此,函数调用不应干预左值到右值的转换以及与任何单个复合赋值运算符相关的副作用。 ——尾注]
正确的操作数怎么样?
“rvalue”和“lvalue”这两个词在整个 5.17 节中不再出现。虽然第 3.10/1 段中的注释明确指出内置赋值运算符期望纯右值作为右操作数,但在第 5.17 节中并未明确提及。即使是 5.17/1 的最后一个注释,它提到了左值到右值的转换,似乎也暗示了右值是预期的(否则需要什么转换?),但注释毕竟是非规范的。
关于其他运算符的部分,包括乘法和加法运算符,通常对其操作数的值类别保持沉默。我在标准中找不到任何“默认语句”指出,如果未另行指定,内置运算符的操作数是右值。因此,问题。
问题:
- 赋值运算符右操作数的值类别是什么;而且,更一般地说
- 不指定时如何判断运算符操作数的值类别?是否不受约束(意味着接受任何值类别)?如果是这样,为什么左值到右值的转换应该应用于赋值表达式?
高度赞赏对 C++11 标准的引用。
【问题讨论】:
-
右侧的值类别是函数参数所期望的(我认为
&&是纯右值,&是左值,const&是任何东西,值是任何东西)。对于所有原始类型,我们可以推断签名是T& operator=(const T&rhs),但我认为它没有在任何地方明确说明。 -
嘿,注释说“第 5 条表示”而不是“第 5 条定义”:) 赋值指示是 5.17p2 “在简单赋值 (=) 中,表达式的值替换了由左操作数引用的对象。"
-
@JohannesSchaub-litb:你知道预期的规范是什么吗?如果定义不明确,我们是否打算假设内置运算符的右操作数在未指定时是右值?
-
@MooingDuck:为什么会这样?对于原始类型,我相信它同样可以是
T& operator=(T)。没有? -
@AndyProwl 不幸的是,我认为没有什么可以说的。我认为规范没有明确规定,并遗漏了承诺的“每个内置运算符的讨论”:)
标签: c++ c++11 operators language-lawyer rvalue