&= 和 |= 运算符是不是用于布尔短路?

Posted

技术标签:

【中文标题】&= 和 |= 运算符是不是用于布尔短路?【英文标题】:Do the &= and |= operators for bool short-circuit?&= 和 |= 运算符是否用于布尔短路? 【发布时间】:2014-05-31 04:35:34 【问题描述】:

在 C++ 中编写这样的代码时:

bool allTrue = true;
allTrue = allTrue && check_foo();
allTrue = allTrue && check_bar();

如果check_foo() 返回false,则不会评估check_bar()。这称为short-circuiting or short-circuit evaluation,是惰性求值原则的一部分。

这是否适用于复合赋值运算符&=

bool allTrue = true;
allTrue &= check_foo();
allTrue &= check_bar(); //what now?

对于逻辑OR,将所有& 替换为|,将true 替换为false

【问题讨论】:

@BenjaminLindley 好的,我稍微改变了我的表述。似乎惰性评估只是意味着如果您不需要程序的某些部分,就跳过它们的评估,就像在常规的 if-else-clauses 中一样。短路更进一步,但似乎遵循相同的基本思想。 @Mehrdad 阅读答案后,我同意你的看法。 C++ 似乎没有任何理由没有 &&= 赋值运算符。 标题中是否有缺字? @n.1 没有?在这种情况下,短路是动词。 好的,谢谢,我不知道这是动词。 【参考方案1】:

来自 C++11 5.17 Assignment and compound assignment operators:

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

但是,您将 短路的逻辑 AND 与永远不会短路的按位 AND 混为一谈。

文本 sn-p &&=,这将是你将如何做你所要求的,在标准中无处。原因是它实际上并不存在:没有逻辑和赋值运算符。

【讨论】:

我的错,可能只是一厢情愿。你知道 C++ 没有&&= 运算符的具体原因吗? @iFreilicht:任何具体原因?可能是因为 C 从来没有它,而最初的 C++ 编译器或多或少只是 C 的前端,意味着“带有类的 C”,而不是“带有类和几个额外运算符的 C”:-) @paxdiabla soooo 为什么 C 没有它?我的意思是,这对我来说肯定是一件有用的事情,而且实施起来也不会太难。 @iFreilicht,C 没有它,因为 Dennis Ritchie 显然 觉得它很有用(我们可以直接问他,如果他没有赶走这个凡人线圈,让我们中的许多人变得更小)。 ANSI C 没有它,因为他们的任务是编纂现有实践而不是创建一种新语言。 ISO 没有它,因为它们基本上是在 ANSI 上加盖了橡皮图章(还不错)。从那时起,它就没有被添加到 C 中,因为它要么没有作为提案提出,要么已经提出,但没有获得足够的选票。我想我不能提供比这更多的细节了:-) @iFreilicht:x &&= y; 有用的情况并不多。如果xy 都已知为零或一,那么if (x) x=y; 会更有效[实际上,如果x 非零,我希望x && y 已被定义为产生y,但这已经晚了几十年]。【参考方案2】:

短路(即惰性)评估仅适用于逻辑&&||。按位 &| 计算两个参数。

【讨论】:

【参考方案3】:

不,它们不会缩短。

请注意,&=|= 运算符的格式为 &+=|+=位运算符 &| 不执行快捷方式计算。

只有布尔运算符 &&|| 执行它。

这意味着,快捷操作符在传统上必须命名为&&=||=。一些语言提供它们。 C/C++ 没有。

【讨论】:

【参考方案4】:

代码allTrue &= check_foo();相当于allTrue = allTrue & check_foo() 您在其中使用 bitwise AND 并且没有执行惰性求值。

bitwise AND 必须取两个二进制表示的长度相同的参数,并使用logical AND 操作来比较每一对对应的位。

【讨论】:

很确定您可以使用&| 进行整数提升,即。 uint16_t x = 0xabcd; uint8_t y = 0xef; uint16_t z = x | y; // z = 0xabef,所以说要求“二进制表示具有相同的长度”是不正确的?【参考方案5】:

首先:a &= b;a = a && b; 不同。 a &= b; 表示 a = a & b;。在 C/C++ 中没有 a &&= b;

逻辑与a && b 有点像对 1 位的测试。如果第一个“位”已经为 0,那么无论第二个结果如何,结果都将始终为 0。因此,如果a 的结果已经很清楚,则无需评估b。 C/C++ 标准允许这种优化。

按位与a & bab 的所有位执行此测试。因此,如果a 中的至少一位不为零,则需要评估b。您可能希望,如果 a==0,而不是 b,则不会被评估,但这种优化在 C/C++ 中是不允许的。

【讨论】:

【参考方案6】:

由于 & 是位运算,check_foo() 将首先被评估,而不考虑 allTrue in 的值

allTrue &= check_foo(); // also for allTrue = allTrue & check_foo();

还有

allTrue &= check_bar(); // also for allTrue = allTrue & check_bar();

但是,如果您使用 && 并且 alltrue 为 false,则不会调用 check_foo(),如下所示:

allTrue = allTrue && check_foo();

【讨论】:

以上是关于&= 和 |= 运算符是不是用于布尔短路?的主要内容,如果未能解决你的问题,请参考以下文章

布尔逻辑运算符

&和&&的区别?

在 C++ 中对布尔值使用位运算符

Julia - 短路求值

JS中短路运算符&&和||

JS中短路运算符&&和||