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

Mes*_*sop 6 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();
    }
Run Code Online (Sandbox Code Playgroud)

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

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

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

void test(int a)
{
    if (a == 1)
    {
        doSomething1();
    }
    else if (a == 2)
    {
        doSomething1();
    }
    else if (a == 3)
    {
        doSomething1();
    }
    else
    {
        doSomething1();
    }
}
Run Code Online (Sandbox Code Playgroud)

Ed *_* S. 7

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

是的,但不是专门用于所有(单线程)代码的if语句.

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

  • 异步调用也按照编写代码的顺序进行 - 它只是异步调用的*效果*可能同时发生或交错发生.我想说,信号处理程序和异步*回调*是(单线程)控制流程中更有趣的部分. (2认同)

out*_*tis 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;
Run Code Online (Sandbox Code Playgroud)

可以等同地重写为

  if (x) {
      int i;
  }
Run Code Online (Sandbox Code Playgroud)

[...]

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();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

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

从6.4.1,内if时用于外部条件被执行的语句iffalse.如果条件是true,则执行第一个分支.虽然标准没有明确说明第二个分支在条件出现时没有执行true,但是遗漏强烈暗示了这一点.

根据§1.91:

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

5)这一规定有时被称为"假设"规则,因为只要结果好像符合要求,只要可以从中确定,实施就可以自由地忽视本国际标准的任何要求.程序的可观察行为.例如,实际实现不需要评估表达式的一部分,如果它可以推断出它的值没有被使用,并且没有产生影响程序的可观察行为的副作用.

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


Jam*_*nze 5

不可以.唯一可以保证的是,可观察的行为"好像"ifs按顺序进行评估.条件的评估甚至可以是交错的,cond2的一部分在cond1之前,而另一部分在cond1之后被评估.另一方面,保证结果将"好像"按顺序评估ifs,如果某些条件有副作用,如果其中一个较早的ifs为真,则不会发生这些副作用.

关于优化,通过一切手段将最可能的条件放在第一位.在实践中,编译器只会在知道运动会改进的情况下移动代码,因此如果条件或多或少独立,并且编译器无法通过折叠部分来"优化"它们,那么将保留顺序.除非编译器特别好,并且可以确定您的排序不是最佳的(基于分析器输出).