C++ bool a |=mayRun()的右手表达式是什么时候;被处决?

C++ bool a |=mayRun()的右手表达式是什么时候;被处决?,c++,compiler-construction,compound-assignment,C++,Compiler Construction,Compound Assignment,假设代码片段 bool a; a = true; a |= mayRun(); a = false; a |= mayRun(); 在哪种情况下执行mayRun() 所有的解释都告诉我 a |=b 相当于 a=a | b 但它不能与示例相同 arr[i++]|=b 指示。由于短路不适用于按位操作(仅适用于逻辑操作,如&&和|) 请注意,这种误解可能会导致严重错误-开发人员会假设存在短路,但没有短路,并且所有表达式部分都会一直执行,这会改变程序逻辑。因为短路不适用于按位操作,所以始终会执行短路

假设代码片段

bool a;
a = true;
a |= mayRun();

a = false;
a |= mayRun();
在哪种情况下执行mayRun()

所有的解释都告诉我
a |=b
相当于
a=a | b

但它不能与示例相同
arr[i++]|=b

指示。

由于短路不适用于按位操作(仅适用于逻辑操作,如
&&
|


请注意,这种误解可能会导致严重错误-开发人员会假设存在短路,但没有短路,并且所有表达式部分都会一直执行,这会改变程序逻辑。

因为短路不适用于按位操作,所以始终会执行短路(仅适用于逻辑操作,如
&&
| |


请注意,这种误解可能会导致严重错误-开发人员会假设存在短路,但没有短路,并且所有表达式部分都会一直执行,这会改变程序逻辑。

它总是被执行。请注意,
a |=b
确实是
a=a | b
(只计算
a
一次)。特别是,它不是
a=a | | b
的简写

这意味着它不提供布尔运算符的短路行为,因此总是计算
b

将这些速记赋值形式与
bool
变量一起使用是危险的,这正是因为语义不明显。
&=
实际上更糟糕。比较一下:

int two() { return 2; }

int main()
{
  bool b = true;
  b = b && two();
  assert(b);  //OK
}
为此:

int two() { return 2; }

int main()
{
  bool b = true;
  b &= two();
  assert(b);  //FAILS!!
  // b &= two(); was actually b = 1 & 2, which is 0 !
}

简而言之,避免对布尔变量使用
|=
&=

它总是被执行。注意
a |=b
确实是
a=a | b
的缩写(只对
a
求值一次)。特别是,它不是
a=a | b
的缩写

这意味着它不提供布尔运算符的短路行为,因此总是计算
b

将这些速记赋值形式与
bool
变量一起使用是危险的,这正是因为语义不明显。
&=
实际上更糟糕。比较一下:

int two() { return 2; }

int main()
{
  bool b = true;
  b = b && two();
  assert(b);  //OK
}
为此:

int two() { return 2; }

int main()
{
  bool b = true;
  b &= two();
  assert(b);  //FAILS!!
  // b &= two(); was actually b = 1 & 2, which is 0 !
}
简而言之,避免对布尔变量使用
|=
&=

在哪种情况下执行
mayRun()

它将永远被执行

也许您希望
|=
执行短路,但事实并非如此:这只发生在逻辑运算符
&&&
|
上,此时结果只能由第一个操作数确定。没有像
| 124;=
这样的逻辑复合赋值运算符,因此短路永远不会发生n赋值表达式

所有的解释都告诉我,
a |=b;
等同于
a=a | b;

差不多;但无论你读了什么解释,都漏掉了一个重要的细节

但它不能与
arr[i++]|=b;
所示的示例相同

事实上,正如C++11 5.17/7所规定的那样,有一个区别:

形式为
E1 op=E2
的表达式的行为等同于
E1=E1 op E2
,只是E1只计算一次

在哪种情况下执行
mayRun()

它将永远被执行

也许您希望
|=
执行短路,但事实并非如此:这只发生在逻辑运算符
&&&
|
上,此时结果只能由第一个操作数确定。没有像
| 124;=
这样的逻辑复合赋值运算符,因此短路永远不会发生n赋值表达式

所有的解释都告诉我,
a |=b;
等同于
a=a | b;

差不多;但无论你读了什么解释,都漏掉了一个重要的细节

但它不能与
arr[i++]|=b;
所示的示例相同

事实上,正如C++11 5.17/7所规定的那样,有一个区别:

形式为
E1 op=E2
的表达式的行为等同于
E1=E1 op E2
,只是E1只计算一次


@nvoigt这将给出一个模编译器错误和特性的答案。对于性能问题,“profile it”是正确的答案。对于“这里应该发生什么”问题,我会小心“proof by compiler”关于最后两句话,除了
a
只计算一次之外,它是等价的。@nvoigt这将给出一个关于模编译器错误和特性的答案。对于性能问题,“profile it”是正确的答案。对于“这里应该发生什么”问题,我会小心“编译器证明”关于最后两句话,除了
a
只评估一次之外,它是等效的。谢谢,这正是我需要的解释级别:-)谢谢,这正是我需要的解释级别:-)