为什么要使用标准C++;赋值表达式的语法看起来很奇怪 从C++标准中,赋值表达式的语法如下: assignment-expression: conditional-expression logical-or-expression assignment-operator assignment-expression throw-expression assignment-operator: one of = *= /= %= += -= >>= <<= &= ^= |= 赋值表达式: 条件表达式 逻辑或表达式赋值运算符赋值表达式 抛出表情 赋值运算符:其中一个 =*=/=%=+=-=>=

为什么要使用标准C++;赋值表达式的语法看起来很奇怪 从C++标准中,赋值表达式的语法如下: assignment-expression: conditional-expression logical-or-expression assignment-operator assignment-expression throw-expression assignment-operator: one of = *= /= %= += -= >>= <<= &= ^= |= 赋值表达式: 条件表达式 逻辑或表达式赋值运算符赋值表达式 抛出表情 赋值运算符:其中一个 =*=/=%=+=-=>=,c++,grammar,C++,Grammar,您的特定语句,(4 | | localvar1)=5无效(除非运算符| |重载),因为您不能将5赋值给4(4是一个r值)。您必须在左侧有一个l值(可以赋值的对象),例如函数返回的引用 例如,假设您有一个函数int&get\u my\u int(),它返回对整数的引用。然后,您可以执行以下操作: `get_my_int() = 5;` 这将把get_my_int()返回的整数设置为5。 就像在第一篇文章中一样,这必须是对整数(而不是值)的引用;否则,上述语句将无法编译。您的特定语句,(4 | |

您的特定语句,
(4 | | localvar1)=5
无效(除非
运算符| |
重载),因为您不能将5赋值给4(4是一个r值)。您必须在左侧有一个l值(可以赋值的对象),例如函数返回的引用

例如,假设您有一个函数
int&get\u my\u int()
,它返回对整数的引用。然后,您可以执行以下操作:

`get_my_int() = 5;`
这将把
get_my_int()
返回的整数设置为
5

就像在第一篇文章中一样,这必须是对整数(而不是值)的引用;否则,上述语句将无法编译。

您的特定语句,
(4 | | localvar1)=5
无效(除非
运算符| |
重载),因为您不能将5赋值给4(4是一个r值)。您必须在左侧有一个l值(可以赋值的对象),例如函数返回的引用

例如,假设您有一个函数
int&get\u my\u int()
,它返回对整数的引用。然后,您可以执行以下操作:

`get_my_int() = 5;`
这将把
get_my_int()
返回的整数设置为
5

就像在第一篇文章中一样,这必须是对整数(而不是值)的引用;否则,上面的语句将无法编译。

语法有点复杂,但是如果您继续使用前面的定义,您将看到赋值表达式非常通用,并且允许大部分内容。虽然您引用的标准中的代码片段主要关注逻辑或表达式,但如果您继续展开其定义,您会发现赋值的左侧和右侧几乎都可以是任何子表达式(尽管不是字面上的任何子表达式)

前面指出的原因是赋值可以应用于枚举或基本类型的任何左值表达式或类类型的右值表达式(其中
运算符=
始终是成员)。在允许运算符重载且不定义运算符返回类型的语言中,许多表达式可能满足赋值的需要,语法必须允许所有这些用途


标准中的不同规则稍后将限制从语法生成的可能表达式中哪些是实际有效的或无效的。

语法有点复杂,但如果继续使用前面的定义,您将看到赋值表达式非常通用,并且几乎允许任何内容。虽然您引用的标准中的代码片段主要关注逻辑或表达式,但如果您继续展开其定义,您会发现赋值的左侧和右侧几乎都可以是任何子表达式(尽管不是字面上的任何子表达式)

前面指出的原因是赋值可以应用于枚举或基本类型的任何左值表达式或类类型的右值表达式(其中
运算符=
始终是成员)。在允许运算符重载且不定义运算符返回类型的语言中,许多表达式可能满足赋值的需要,语法必须允许所有这些用途


标准中的不同规则将限制从语法生成的可能表达式中的哪一个实际上是有效的。

< P>赋值语句的C++语法实际上有两个有趣的事情,都与:

的有效性无关。
 (4 || localvar1) = 5;
由于有括号,该表达式在语法上是有效的(直到类型检查)。在赋值运算符的左侧,引用类型的任何括号表达式在语法上都是正确的。(正如已经指出的,由于运算符重载,几乎任何涉及用户类型或函数的表达式都可以是引用类型。)

语法中更有趣的是,它将赋值运算符的左优先级设置为低于几乎所有其他运算符(包括逻辑or),因此上述表达式在语义上与

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;
与赋值运算符相比,在赋值运算符左侧绑定不太紧密的其他运算符只有
运算符和另一个赋值运算符。(换句话说,赋值是右联想的,与几乎所有其他二元运算符不同。)这两种方法都不令人惊讶——事实上,它们是如此必要,以至于很容易忽略以这种方式设计语法的重要性。考虑以下不寻常的<代码> < /COD> >子句:

for (first = p = vec.begin(), last = vec.end(); p < last; ++p)
for(first=p=vec.begin(),last=vec.end();p
这里的
是一个逗号运算符,它显然需要绑定更少的ti