根据C++标准,赋值表达式的语法如下:
assignment-expression:
conditional-expression
logical-or-expression assignment-operator assignment-expression
throw-expression
assignment-operator: one of
= *= /= %= += -= >>= <<= &= ^= |=注意,“赋值运算符”的左边是“逻辑-或表达式”,即类似于(4 \x- localvar1) =5的东西;根据语法,是一个有效的赋值表达式。这对我来说毫无意义。为什么他们选择“逻辑或表达式”,而不是,比如说,一个标识符或id_expression?
发布于 2013-08-22 13:15:24
语法有点复杂,但是如果您继续使用前面的定义,您将看到赋值表达式是非常通用的,并且允许大多数情况下使用。虽然您引用的标准中的片段侧重于逻辑或表达式,但是如果您继续展开它的定义,您会发现赋值的左手和右手都可以是几乎任何子表达式(尽管不是字面上的任何子表达式)。
如前所述,原因是赋值可以应用于枚举的任何lvalue表达式或类类型的基本类型或rvalue表达式(其中operator=始终是成员)。在一种允许运算符重载且不定义从运算符返回的类型的语言中,许多表达式可能满足赋值的需要,语法必须允许所有这些用途。
标准中的不同规则稍后将限制可以从语法生成的可能表达式中哪些实际上有效或不有效。
发布于 2013-08-22 13:07:22
您的特定语句(4 || localvar1) = 5;无效(除非operator||重载),因为您不能分配5到4 (4是r值)。您必须在左边有一个l值(可以赋值),例如函数返回的引用。
例如,假设您有一些函数int& get_my_int(),它返回对整数的引用。然后,你可以这样做:
`get_my_int() = 5;`这将将get_my_int()返回的整数设置为5。就像在第一篇文章中一样,这必须是对整数(而不是值)的引用;否则,上面的语句将不会编译。
发布于 2013-08-22 14:25:49
实际上,关于赋值语句的C++语法有两件有趣的事情,这两件事都与以下两种语句的有效性无关:
(4 || localvar1) = 5;由于括号的存在,该表达式在语法上是有效的(直到类型检查)。在赋值运算符的左侧,任何带括号的引用类型表达式在语法上都是正确的.(而且,正如已经指出的,由于运算符重载,几乎任何涉及用户类型或函数的表达式都可以是引用类型)。
语法更有趣的是,它将赋值运算符的左优先级确定为比几乎所有其他运算符(包括逻辑运算符)都低,因此上述表达式在语义上相当于
4 || localvar1 = 5;尽管许多读者会将上面的内容解释为4 || (localvar1 = 5) (假设localvar1是一种可以由int分配的类型,这是完全正确的,尽管所述的赋值永远不会发生--当然,除非||在这种情况下超载)。
那么,在赋值运算符的左边,什么优先级较低呢?正如我说的,很少,但一个重要的例外是?:
// Replace the larger of a and b with c
a > b ? a = c : b = c;是有效和方便的括号-少。(许多风格指南在这里坚持使用多余的括号,但我个人更喜欢非括号的版本。)这与右边的优先级不一样,因此下面的操作也不带括号:
// Replace c with the larger of a and b
c = a > b ? a : b;在赋值运算符左边绑定较少的其他运算符是,运算符和另一个赋值运算符。(换句话说,与几乎所有其他二进制运算符不同,赋值是正确结合的。)这两个都不令人惊讶--事实上,它们是如此的必要,以至于我们很容易忽视以这种方式设计语法是多么的重要。考虑以下不值得注意的for条款:
for (first = p = vec.begin(), last = vec.end(); p < last; ++p)在这里,,是一个逗号运算符,它显然需要比围绕它的任何一个赋值绑定得更少。(在这种语法中,C和C++只有一个逗号运算符才是例外;在大多数语言中,,不被认为是运算符。)而且,将第一个赋值表达式解析为(first = p) = vec.begin()显然是不可取的。
赋值运算符与右关联这一事实并不显著,但值得注意的是历史上的一种好奇心。当Bjarne四处寻找操作符过载I/O流时,他选择了<<和>>,因为虽然赋值操作符可能更自然一些,但是赋值绑定到右边,而流运算符必须绑定到左边(std::cout << a << b必须是(std::cout << a) << b) )。但是,由于<<的绑定比分配紧密得多,所以在使用流运算符时存在许多问题。(最近我发现的是,移位比按位运算符绑定得更紧密。)
注1:我没有这方面的引文,但我记得很多年前用C++编程语言阅读过它。我记得,对于赋值运算符是自然的,并没有达成共识,但似乎比重载移位运算符更自然的是,它与它们的正常语义完全不同。
https://stackoverflow.com/questions/18381217
复制相似问题