6

if-else if-else if-elseブロックのifが書き込まれた順序でテストされるという保証はありますか。

最も頻繁なケースを最初に置くことでコードを最適化しようとすることがよくあり、コンパイラーによって行われた最適化によって 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がテストされ、次に2番目のif、次に3番目のifがテストされるという保証はありますか(そして、条件がどれも真でない場合、最後にelseが実行されます)。

デバッグ時には、if は私が書いた順序で実行されることはわかっていますが、プログラムがリリース用にコンパイルされるときもそのままです (私は主に 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();
    }
}
4

5 に答える 5

7

Is there any guarantee that after being compiled (for release), the first if will be tested, then the second if, then the third if (and finally the else is executed if none of the condition was true).

Yes, but not specifically for if statements, for all of your (single threaded) code.

C++ code is executed top down, from the beginning to the end. The only time this may not be the case is when you make asynchronous calls or have multiple threads calling the same code simultaneously.

于 2012-05-09T18:23:02.337 に答える
6

C++03 から、§ 6.4 選択ステートメント:

1

選択ステートメント:
     if (条件)
     if (条件)else
     switch (条件)
[...] selection-statement のサブステートメントが単一のステートメントであり、compound-statementではない場合、元のサブステートメントを含む複合ステートメントに書き直されたかのようになります。[例:

  if (x)
     int i;

と同等に書き換えることができます

  if (x) {
      int i;
  }

[...]

6.4.1ifステートメント

1 条件 (6.4) が生成される場合true、最初のサブステートメントが実行されます。else選択ステートメントの一部が存在し、条件が を生成するfalse場合、2 番目のサブステートメントが実行されます。[...]

6.4 1 以降、サンプル コードは次のようになります。

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

これは、コードが上記のように変換されることを意味するのではなく、2 つのコードが同じように動作する必要があることに注意してください。

6.4.1 からif、outer の条件が の場合、inner ステートメントが実行されifますfalse。条件が の場合true、最初の分岐が実行されます。標準では、条件が の場合に 2 番目の分岐が実行されないと明示的に述べていませんがtrue、省略によって強く暗示されています。

§ 1.9 1 によると:

この国際標準のセマンティック記述は、パラメータ化された非決定論的抽象マシンを定義します。この国際規格は、適合する実装の構造に要件を課していません。特に、抽象マシンの構造をコピーまたはエミュレートする必要はありません。むしろ、以下で説明するように、抽象マシンの観察可能な動作をエミュレートする (のみ) ために、適合する実装が必要です。5)

5)この規定は、「as-if」ルールと呼ばれることもあります。これは、実装が、あたかも要件が遵守されたかのように結果が得られる限り、実装がこの国際規格の要件を自由に無視できるためです。プログラムの観察可能な動作。たとえば、実際の実装では、式の値が使用されておらず、プログラムの観察可能な動作に影響を与える副作用がないと推測できる場合、式の一部を評価する必要はありません。

そのため、サブステートメントの一部は、else副作用がなく、条件がtrue. たとえば、サブステートメント条件は、分岐予測で条件が になると誤って予測された場合、プロセッサパイプライン内で部分的に実行される可能性があります。ただし、これによる影響は目立ってはならないため、(あなたの観点からは) サブステートメントが 6.4 1 および 6.4.1 1 で概説されているように動作しているように見えます。false

于 2012-05-09T18:37:55.197 に答える
5

いいえ。保証される唯一のことは、観察可能な動作が「あたかも」ifsが順番に評価されたかのようであるということです。条件の評価は、cond2の一部がcond1の前にあり、cond1の後に別の部分が評価された状態でインターリーブされる場合もあります。一方、結果が「あたかも」ifが順番に評価されたかのように保証されます。一部の条件に副作用がある場合、以前のifのいずれかが真であれば、それらの副作用は発生しません。

最適化に関しては、必ず最も可能性の高い条件を最初に置いてください。実際には、コンパイラーは、移動によって状況が改善されることがわかっている場合にのみコードを移動します。したがって、条件が多かれ少なかれ独立していて、コンパイラーがコードの一部を折りたたんで「最適化」できない場合、順序は保持されます。コンパイラーが非常に優れていて、(プロファイラーの出力に基づいて)順序が最適でないと判断できる場合を除きます。

于 2012-05-09T18:29:17.650 に答える
0

C ++コンパイラは、いくつかの例外を除いて、他の何かが最適化されていないステートメントを実行しているかのように動作する限り、ステートメントを何かに最適化することのみが許可されます。

if / elseタワーのステートメントを並べ替えても、並べ替えられていない場合は「あたかも」動作しません(もちろん、一部のチェックが常にtrueまたはfalseであり、副作用がない場合のように、コンパイラがそれを証明できる場合を除きます)。 。

あなたは絶対にあなたのif/elseタワーの順序に依存することができます。

于 2012-05-09T18:28:39.583 に答える
0

yes, the conditions are checked in the order of the if, else if, else structure. Within a given conditional check, things can be tweaked a bit with parentheses.

于 2012-05-09T18:22:52.507 に答える