&= 和 |= 运算符是不是用于布尔短路?
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;
有用的情况并不多。如果x
和y
都已知为零或一,那么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 & b
对a
和b
的所有位执行此测试。因此,如果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();
【讨论】:
以上是关于&= 和 |= 运算符是不是用于布尔短路?的主要内容,如果未能解决你的问题,请参考以下文章