【问题标题】:Logical AND, OR: Is left-to-right evaluation guaranteed?逻辑与、或:是否保证从左到右的评估?
【发布时间】:2011-08-06 16:24:00
【问题描述】:

是否保证逻辑运算符 (&&||) 的从左到右求值?

假设我有这个:

SDL_Event event;

if (SDL_PollEvent(&event)) {
    if (event.type == SDL_QUIT) {
            // do stuff
    }
}

这个保证和这个一样吗?

SDL_Event event;

if (SDL_PollEvent(&event) && event.type == SDL_QUIT) {
    // do stuff
}

这也很重要,假设我们有两个要求,ab。需求ab 更有可能失败。那么说if (a && b)if (b && a) 更有效率。

【问题讨论】:

  • && 暗示的排序的一个经典而重要的用途是在使用前测试空指针:if (a != 0 && a->b != 0 && a->b->c != 0) { somefunc(a->b->c->d); }。该顺序对于避免核心转储至关重要。 (为了说明,我忽略了得墨忒耳定律!)
  • @Jonathan:我忽略它是为了完成任何工作!
  • 这些不是“比较”运算符。

标签: c++ logical-operators operator-precedence


【解决方案1】:

是的,这是有保证的,否则这样的运算符将失去很多用处。

重要提示:这对内置&&|| 有效;如果某些犯罪分子重载它们,它们将被视为“常规”重载二元运算符,因此在这种情况下,两个操作数都总是被评估,并且像往常一样以未指定的顺序进行评估。出于这个原因,永远不要让它们超载——它打破了关于程序控制流的一个非常重要的假设。


相关标准引用

内置&&|| 保证短路行为

§5.14 ¶1

& 不同,&& 保证从左到右评估:如果第一个操作数是 false,则不评估第二个操作数。

§5.15 ¶1

| 不同,|| 保证从左到右的评估;此外,如果第一个操作数的计算结果为 true,则不会计算第二个操作数。

如果重载,它们的行为类似于“常规”二元运算符(没有短路或有保证的求值顺序)

§13.5 ¶9

在 13.5.3 到 13.5.7 小节中未明确提及的运算符充当普通的一元和二元运算符,遵守 13.5.1 或 13.5.2 的规则。

&&|| 在这些子条款中没有明确提及,因此常规 §13.5.2 成立:

§13.5.2 ¶1

二元运算符应由具有一个参数的非静态成员函数(9.3)或具有两个参数的非成员函数实现。因此,对于任何二元运算符@x@y 都可以解释为 x.operator@(y)operator@(x,y)

没有对仅评估一侧或以特定顺序进行评估的特殊规定。

(所有来自 C++11 标准的引用)

【讨论】:

  • 顺便说一句,请记住,如果您有“简单”条件(例如您的第二个条件),则分支的成本可能高于评估条件本身。
  • Matteo Italia:ab 是假设性的。它们可能是IsPrime(n)IsEven(n),其中正确的顺序非常明显,可以节省大量资金。
  • @nightcracker:当然,我只是指出了一个小而常见的误解。 :)
  • 没有副作用的条件可以移动到编译器喜欢的任何地方。允许编译器消除分支。
  • @MatteoItali不再保证评估。[
猜你喜欢
  • 2012-09-26
  • 2011-08-30
  • 2012-01-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-18
  • 2020-06-15
相关资源
最近更新 更多