是否按照编写的顺序测试if是否为if-else ... if-else ... if-else阻止?

时间:2012-05-09 18:20:36

标签: c++ if-statement

是否有任何保证,if-else if-else if-else块的ifs按照它们的编写顺序进行测试。

我问的是因为我经常尝试通过最频繁的案例来首先优化我的代码,并且我想知道编译器完成的某些优化是否会改变测试if的顺序。

所以,如果我正在写这样的代码:

    if (cond1) // First if (for the case I have the most often)
    {
            doSomething1();
    }
    else if (cond2) // Second if (for the second case I have the most often)
    {
            doSomething2();
    }
    else if (cond3) // Third if (for the third case I have the most often)
    {
            doSomething3();
    }
    else
    {
            doElse();
    }

是否有任何保证在编译后(发布),第一个if将被测试,然后是第二个if,然后是第三个if(如果没有条件为真,则最后执行else)

我知道在调试时,ifs按照我编写的顺序执行,但是当程序编译发布时它会保持正确(我主要使用g ++和visual studio的最新版本)。

此外,由于条件可能会对环境产生影响(如if (i=a)if(myfunction())),它们应该按照书面执行,但我想知道我是否遗漏了编译器可以进行的一些优化do,这会改变测试ifs的顺序。特别是,如果条件没有这样的副作用:

void test(int a)
{
    if (a == 1)
    {
        doSomething1();
    }
    else if (a == 2)
    {
        doSomething1();
    }
    else if (a == 3)
    {
        doSomething1();
    }
    else
    {
        doSomething1();
    }
}

5 个答案:

答案 0 :(得分:7)

  

有没有保证在编译之后(发布),第一个if将被测试,然后是第二个if,然后是第三个if(如果没有条件为真,则最后执行else)。

是的,但不是专门针对if语句,所有(单线程)代码。

C ++代码从头到尾自上而下执行。唯一的情况可能不是这种情况,当你进行异步调用或让多个线程同时调用相同的代码时。

答案 1 :(得分:6)

来自C ++ 03,§6.4选择陈述:

  

1

selection-statement:
     if ( condition ) statement
     if ( condition ) statement else statement
     switch ( condition ) statement
  [...]   如果selection-statement中的子语句是单个语句而不是复合语句,则就好像它被重写为包含原始子语句的复合语句一样。 [实施例:

  if (x)
     int i;
     

可以等效地重写为

  if (x) {
      int i;
  }
     

[...]

     

6.4.1 if语句

     

1如果条件(6.4)产生true,则执行第一个子语句。如果选择语句的else部分存在且条件产生false,则执行第二个子语句。 [...]

从6.4 1开始,您的示例代码相当于:

if (cond1) {
    doSomething1();
} else {
    if (cond2) {
        doSomething2();
    } else {
        if (cond3) {
            doSomething3();
        } else {
            doElse();
        }
    }
}

请注意,这并不意味着代码转换为上述代码,而是两者必须表现相同。

从6.4.1开始,当外部if的条件为if时,将执行内部false语句。如果条件为true,则执行第一个分支。虽然标准没有明确说明条件为true时没有执行第二个分支,但是遗漏强烈暗示了这一点。

根据§1.91:

  

本国际标准中的语义描述定义了参数化的非确定性抽象机器。本国际标准对符合实施的结构没有要求。特别是,它们不需要复制或模拟抽象机器的结构。相反,需要符合实现来模拟(仅)抽象机器的可观察行为,如下所述。 5)

     

5)此条款有时被称为“as-if”规则,因为只要结果就像<一样,实施可以自由地忽略本国际标准的任何要求/ em>只要可以从程序的可观察行为中确定,就已遵守该要求。例如,实际实现不需要评估表达式的一部分,如果它可以推断出它的值没有被使用,并且没有产生影响程序的可观察行为的副作用。

因此,else子语句的一部分可以在没有副作用的情况下执行,即使条件为true,结果也会被丢弃。例如,如果pipeline错误地预测条件将是false,则可以在处理器branch prediction内部分地执行子语句条件。但是,这种情况的影响必须是不明显的,因此(从您的角度来看),就好像这些子语句的行为符合§6.41和6.4.1 1所述。

答案 2 :(得分:5)

没有。唯一可以保证的是可观察的行为 “似乎”ifs按顺序进行评估。评价 条件甚至可以交错,cond2的一部分在cond1之前, 并且评估了cond1之后的另一部分。另一方面, 保证结果将“好像”ifs已被评估 顺序,如果某些条件有副作用,那些副作用 如果其中一个早期的ifs是真的,就不会发生。

关于优化,无论如何最有可能 条件优先。在实践中,编译器只会移动代码 知道运动会改善事物,所以如果条件是这样的话 或多或少独立,编译器无法“优化”它们 折叠它们的部分,然后订单将被保留。除非 编译器非常好,可以确定您的订购 不是最优的(基于分析器输出)。

答案 3 :(得分:0)

是的,条件是按if,else if,else结构的顺序检查的。 在给定的条件检查中,可以用括号稍微调整一些东西。

答案 4 :(得分:0)

除了少数例外,只允许C ++编译器将语句优化为某种东西,只要其他东西表现为“as-if”它正在执行非优化语句。

重新排序if / else塔的语句不会表现为“as-if”它没有被重新排序(除非编译器当然可以证明它会是,就像某些检查总是真或假并且没有副作用)。

您绝对可以依赖if / else塔的订购。