1

假设代码片段

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

a = false;
a |= mayRun();

在什么情况下执行 mayRun()?

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

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

4

3 回答 3

7

它将始终执行,因为短路不适用于按位运算(仅适用于 and 等逻辑运算&&||

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

于 2013-12-02T11:28:20.917 回答
5

它总是被执行。请注意,这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 !
}

简而言之,避免将|=and&=与布尔变量一起使用。

于 2013-12-02T11:32:03.037 回答
0

在什么情况下mayRun()被执行?

它总是会被执行。

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

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

几乎; 但是,无论您一直在阅读什么解释,都错过了一个重要的细节。

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

实际上,正如 C++11 5.17/7 所指定的那样,存在差异:

除了 E1 只计算一次之外,该形式的表达式的行为E1 op = E2等价于。E1 = E1 op E2

于 2013-12-02T11:44:54.213 回答