7

我在网上看了很多,似乎很多人提到了以下规则(但我在标准中找不到),

加法运算符 +(和所有其他二元运算符)要求两个操作数都是右值,结果是右值。等等..

我检查了 C++ 标准,它明确指出(第 3.10/2 条),

每当一个泛右值出现在预期纯右值的上下文中时,该泛左值就会被转换为一个纯右值

(第 5/9 条),

每当一个泛左值表达式作为操作数的操作数出现时,该操作数需要一个纯右值,左值到右值 (4.1)、数组到指针 (4.2) 或函数到指针 (4.3) 标准转换是应用于将表达式转换为纯右值。

它使用操作数“期望”一个纯右值的术语。但是,当我研究加法运算符、乘法运算符等时,它只提到结果是纯右值,但没有说明操作数“预期”是什么。

二元运算符是否真的期望操作数是纯右值在以下情况下会有所不同,

int b = 2;
int a = b + 1;

如果b期望是prvalue,这里会有一个lvalue到rvalue的转换,然后会执行prvalue + prvalue,返回一个prvalue,结果prvalue赋值给一个lvalue a。

但是,如果 b 不需要是纯右值,它将是左值 + 纯右值,结果是纯右值。

我真的很想知道标准在哪里明确或隐含地提到了不同运营商的规则?我检查了所有操作符部分,并且只有少数标准明确提到操作数和结果应该是左值还是右值。对于大多数运算符,该标准仅提及结果而不提及操作数要求。

谢谢。


顺便说一句,我在标准 5.19 中发现关于常量表达式的内容可能非常“隐含”地暗示二元运算符需要对操作数进行左值到右值的转换。更详细的可以参考我之前的问题,

混合使用 constexpr 和 const?

条件表达式是一个常量表达式,除非它涉及以下之一作为潜在评估的子表达式 (3.2)。

...

— 左值到右值的转换 (4.1),除非它应用于

———— 一个整数或枚举类型的左值,它引用一个非易失性的 const 对象,前面有初始化,用常量表达式初始化

谢谢阅读。

4

2 回答 2

5

因此,这通常是标准的那些推断和错误指定的部分之一;但是,在 3.10

[ 注意:一些内置运算符需要左值操作数。[ 示例:内置赋值运算符都希望它们的左操作数是左值。— 结束示例] 其他内置运算符产生右值,有些人期望它们。[ 示例:一元和二元 + 运算符期望右值参数并产生右值结果。— 结束示例] 第 5 节中对每个内置运算符的讨论表明它是否需要左值操作数以及它是否产生左值。——尾注]

请注意,“第 5 条中指定的语言表明它是否需要左值操作数以及它是否产生左值”。

对第 5 章的检查表明,表达式需要或返回左值的每个情况都被枚举,但是很少有专门处理右值的情况被枚举,我认为然后假设其余的情况被假定为右值。

我还怀疑它的指定很差,因为从标准的角度来看,如果转换是由操作员隐式或显式完成的,这并不是特别重要,无论如何,行为应该是一致的和行为良好的。

于 2011-02-24T07:45:37.053 回答
1

(首先,对不起我的英语。绝对欢迎指正)

标准说:

§5.7-3 二元 + 运算符的结果是操作数的和。[...]

假设我们有表达式e1 + e2,并且+选择的运算符是内置的,表达式格式正确,e1并且e2是算术类型或可以转换为算术类型,一切正常,完美!

因此,适用规则 §5.7-3。另一方面,每个操作数都是一个表达式:

§5-1 [注意:[...] 表达式是指定计算的运算符和操作数序列。表达式可能会产生一个值并可能导致副作用。——尾注]

它说一个表达式可以因为表达式而产生一个值void,比如delete表达式或void函数,但是由于我们说e1 + e2的是一个完美定义的表达式!,我们可以省略动词“can”,因此我们可以确认:表达式产生一个值

最后一点:对于算术和逻辑内置运算符,我理解,虽然标准没有规定,但只有其操作数的值很重要,而与它们的值类别无关。

我认为作为表达式足以实现内置运算符+(和其他算术运算符),因为只有值很重要,并且可以通过表达式达到值。出于这个原因,标准没有明确定义它们。

尽管如此,这类事情的结构非常糟糕。例如,我发现没有指定位置,当运算符接收对象作为操作数而不是直接值时(怀疑我目前正在尝试解决),如果运算符应该直接取其值来计算运算符,如果该值是评估对象的结果,依此类推。很明显,只有价值观很重要,但是,这些东西的标准究竟是什么,却是一种谜。

于 2014-02-10T15:05:27.457 回答