C++运算符的操作数如果未指定,则其值类别是什么?

19

前提:

C++11标准将表达式分类为三种不相交的值类别:左值(lvalues)、右值引用(xvalues)和纯右值(prvalues)(§3.10/1)。可以在此处找到有关值类别的解释,例如这里

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

[...]每个表达式都属于此分类法中的一种基本分类,即左值、右值引用或纯右值。表达式的这个属性称为其值类别。(注:在第5条款中,每个内置运算符的讨论都指出了它产生的值的类别以及它所期望的操作数的值类别。例如,内置赋值运算符期望左操作数为左值,右操作数为纯右值,产生一个左值作为结果。用户定义的运算符是函数,它们期望和产生的值的类别由它们的参数和返回类型确定。—结束注释]。

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

赋值运算符(=)和复合赋值运算符都是从右向左结合的。它们都需要一个可修改的左值作为左操作数,并返回引用左操作数的左值。

如果左操作数是位域,则所有情况下的结果都是位域。在所有情况下,赋值在右操作数和左操作数的值计算之后进行,赋值表达式的值计算之前进行。关于不确定顺序的函数调用,在复合赋值的操作中,是单个评估。注意:因此,函数调用不能介入左值到右值转换和任何单个复合赋值运算符相关的副作用之间。 - 结束注释

那右操作数呢?

在整个第5.17节中,不再出现“rvalue”和“lvalue”这两个词。虽然第3.10 / 1段的注释明确说明内置的赋值运算符期望prvalue作为右操作数,但这在第5.17节中没有明确提到。甚至最后一条注释5.17 / 1也提到了左值到右值的转换,似乎暗示着某种程度上期望rvalue(否则没有必要进行转换),但毕竟注释都是非规范性的。

涉及其他运算符的章节,包括乘法运算符和加法运算符,通常对其操作数的值类别保持沉默。我找不到标准中任何“默认语句”,说明当未另行指定时,内置运算符的操作数是rvalue。因此,这个问题。

问题:

  1. 赋值运算符右操作数的值类别是什么;更一般地说
  2. 在没有规定操作数的值类别时,如何确定运算符的操作数的值类别?它是无约束的(意味着接受任何值类别)吗?如果是这样,为什么左值到右值的转换会应用于赋值表达式?

非常感谢您提供C++11标准的参考。


@JohannesSchaub-litb:你知道预期的规范是什么吗?如果规范定义不清楚,我们是否应该假定未指定内置运算符的右操作数为rvalue? - Andy Prowl
@MooingDuck:为什么呢?对于原始类型,我认为T&operator =(T)同样适用。不是吗? - Andy Prowl
很遗憾,@AndyProwl,我认为没有什么确定的结论可以说。我认为规范说明不清楚,而且忽略了承诺的“每个内置运算符的讨论” :) - Johannes Schaub - litb
恭喜你达到了1万分!这是你在SO上的第一个账户吗?你看起来真的很厉害。:) - David G
@sftrabbit,那个缺陷报告有更新了吗?我问了这个问题:当应用间接寻址时,标准是否要求将左值转换为右值的指针变量?,然后被引导到了这个线程,那个缺陷报告的答案也应该能回答我的问题。 - Shafik Yaghmour
显示剩余13条评论
1个回答

7

是的,它的规范性不明确,之前已经有过讨论。基本上,每当需要枚举lvalue表达式时,我们就假定其他每个操作数都必须是prvalue表达式。

所以回答你的问题:

  1. 一个prvalue。
  2. 如果没有指定,那么它是一个prvalue。

引用链接答案中的注释似乎已经改变了几次。 C++11标准第3.10节中引用的语句如下(当前时间最新草案中相同):

【注】第5条中对每个内置运算符的讨论指出了它产生的值的类别和它期望的运算元的值类别。例如,内置赋值运算符期望左操作数是lvalue并且右操作数是prvalue,并将一个lvalue作为结果产生。用户定义的运算符是函数,它们期望和产生的值的类别由它们的参数和返回类型确定。--注解结束]

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


我在标准的草案中找不到你链接的答案所谓的3.10部分的措辞。n3485草案有什么不同吗?我没有原始的标准。例如,缺少“*[例如:一元和二元+运算符期望rvalue参数并产生rvalue结果。-结束示例] *”。另外,如果未指定,为什么我们可以“假设每个其他操作数必须是prvalue表达式”? - Andy Prowl
@AndyProwl 我同意我们必须假设一些未明确规定的事情是很愚蠢的,但不幸的是这个问题并没有被很好地定义。这是编译器开发人员基本上达成了共识的一个问题。从逻辑上讲,如果操作需要使用操作数的值,那么操作数就是一个prvalue。我正在查看是否有关于此问题的报告。 - Joseph Mansfield
谢谢,你的回答基本上证实了我怀疑的事情,尽管我希望这只是我的疏忽。+1,如果没有更令人信服的答案,我会在几个小时内接受它。 - Andy Prowl
@AndyProwl 很抱歉,我已经快速搜索了问题列表,但没有找到任何相关的内容。 - Joseph Mansfield
如果有任何规范语言支持它,这个答案就很好。不幸的是,这些注释本身并不是语言定义的一部分。您是否知道是否有任何规范语言支持(非常合理的)猜想,即任何未指定的操作数都具有prvalue类别? - user3188445

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接