C ++関数パラメーターでの評価の順序


89

このように構成された3つの関数(foo、bar、baz)がある場合...

foo(bar(), baz())

C ++標準によって、barがbazの前に評価されるという保証はありますか?

回答:


101

いいえ、そのような保証はありません。C ++標準によれば、仕様は規定されていません。

Bjarne Stroustrupは、「C ++プログラミング言語」の第3版のセクション6.2.2でも、それをいくつかの理由で明示的に述べています。

式の評価順序に制限がない場合、より良いコードを生成できます

技術的にはこれは同じセクションの前の部分を指しますが、式の部分の評価の順序も指定されていません。

int x = f(2) + g(3);   // unspecified whether f() or g() is called first

私は8分でこの答えを受け入れることができます...私は少し固執していると思います!
クラークゲーベル、2010年

4
はい。ただし、式の評価順序がSTRICTの場合、コードの生成よりもはるかに重要なコードであれば、より適切なコードを書くことができます(=よりクリーン)。この例を参照してください:stackoverflow.com/questions/43612592/…そこで、Stroustrupです。
ビル・コティアス2017

1
注文が重要な場合は、自分でシーケンスを自由に行うことができます。それ以外の場合、常に(まれに)問題とはならないことに対して常にコストが発生します。ほとんどのC ++プログラマーが同意するのは、使用しないものに料金を払わないというポリシーだけだと思います。
tweej

3
「未定義」ではなく「不特定の動作」であるべきではないでしょうか。
GoodDeeds

1
@ChrisDoddは、「未定義」と「未指定」という単語を使用したために受け入れられた回答に反対票を投じるのは、私にとって悪意のある行動のように感じます...これは「未定義の動作」であるとは言いませんでした。同義?いずれにせよ、回答の編集を提案することは、これを議論するためのより生産的な方法だったでしょう
Eli Bendersky

20

bar()とbaz()の順序は指定されていません-標準が言う唯一のことは、両方がfoo()が呼び出される前に評価されるということです。C ++標準のセクション5.2.2 / 8から:

引数の評価順序は不定です。


4
それらがfoo()の前に評価されるという事実は、少なくとも少し安心です。
Bill Kotsias

1
@BillKotsias標準では、関数呼び出しはオーバーラップできない(つまり、実装はの1行目bar、次に1行目baz、次に2行目barなどを実行できない)とも述べており、これも便利です。:-)
メルポメン

20

[5.2.2]関数呼び出しから、

引数の評価順序は不定です。引数式評価のすべての副作用は、関数に入る前に有効になります。

そのため、保証はありませんbar()前に実行されるbaz()のみであること、bar()そしてbaz()前に呼び出されますfoo

[5]式から、次の点にも注意してください。

特に明記されていない限り(たとえば、&&およびの特別なルール||)、個々の演算子のオペランドと個々の式の部分式の評価の順序、および副作用が発生する順序は、規定されていません。

そのため、でbar()以前baz()に実行するかどうかを尋ねていたとしてもfoo(bar() + baz())、順序はまだ指定されていません。


4
[5.14]論理AND演算子の「特記事項」の例:「とは異なり&&&左から右への評価が保証されfalseます。最初のオペランドがの場合、2番目のオペランドは評価されません。」
Daniel Trebbien


2

C ++ 11では、関連するテキストは8.3.6デフォルトの引数/ 9(Emphasis mine)にあります。

デフォルトの引数は、関数が呼び出されるたびに評価されます。関数の引数の評価順序は不定です。したがって、関数のパラメーターは、評価されない場合でも、デフォルトの引数で使用されません。

同じ言い回しがC ++ 14標準でも使用されており、同じセクションにあります。


0

他の人がすでに指摘したように、この規格では、この特定のシナリオの評価順序に関するガイダンスは提供されていません。この評価の順序はコンパイラーに委ねられ、コンパイラーが保証する場合があります。

C ++標準は、実際にはコンパイラにアセンブリ/マシンコードの構築を指示する言語であることを覚えておくことが重要です。標準は方程式の一部にすぎません。標準があいまいであるか、実装が明確に定義されている場合は、コンパイラーを使用して、C ++命令を真の機械語に変換する方法を理解する必要があります。

したがって、評価の順序が要件であるか、少なくとも重要であり、クロスコンパイラー互換であることは要件ではない場合、コンパイラーが最終的にこれをどのように組み合わせるかを調査すると、答えは最終的にそこにあります。コンパイラは将来的にその方法を変更する可能性があることに注意してください

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.