15

私が書く場合、私は評価の前にf(x)->g(args, ...)シーケンスポイントに頼ることができますか?私は両方の方法で議論を見ることができます:f(x)args, ...

  • §1.9.17「関数を呼び出す場合(関数がインラインであるかどうかに関係なく)、すべての関数の引数(存在する場合)の評価後、関数本体の式またはステートメントの実行前に実行されるシーケンスポイントがあります。戻り値のコピー後、関数外の式の実行前にもシーケンスポイントがあります。
  • 一方、オブジェクトポインタは、this私が書いたかのように暗黙的に非表示の引数g(f(x), args, ...)であり、引数のようなものであり、したがって指定されていないことを示唆しています。

->演算子は通常の二項演算子ではありません。これは、私が書いた場合のように、以前は明らかに評価できg(...) ないためです。私はそれについての特定の声明を見つけることができないことに驚いています。f(x)f(x) + g(...)

4

2 に答える 2

13

答えは、使用している(またはコンパイラが使用している)C++標準のバージョンによって異なります。

C ++ 2003 5.2.2 p8によると:

引数の評価の順序は指定されていません。引数式の評価のすべての副作用は、関数に入る前に有効になります。後置式と引数式リストの評価順序は未定です。

これは、評価との間にシーケンスポイントがないことを意味します。f(x)args

C ++ 2011では、シーケンスポイントの概念全体が置き換えられ(N1944を参照)、その表現は単なるメモになりました。

[注:接尾辞式と引数式の評価はすべて、相互に順序付けられていません。引数式の評価のすべての副作用は、関数に入る前に順序付けられます(1.9を参照)。—エンドノート]

と1.9p15は言う

関数を呼び出すとき(関数がインラインであるかどうかに関係なく)、引数式、または呼び出された関数を指定する後置式に関連するすべての値の計算と副作用は、本体のすべての式またはステートメントの実行前にシーケンスされます。関数と呼ばれます。[注:異なる引数式に関連する値の計算と副作用は順序付けられていません。—エンドノート]

これは、式f(x)と式argsがの本体のすべての前にg順序付けられているが、それらは相互に順序付けられていないことを示しています。これは、C ++ 03の規則と同じですが、言い回しが異なります。

C++14にはC++11と同じルールがありますが、以下のコメントに記載されているように、ルールはC++17で変更されました。

C ++ 2017 8.2.2 [expr.call] p5によると:

postfix-expressionは、expression-listの各式とデフォルトの引数の前にシーケンスされます。関連するすべての値の計算と副作用を含むパラメーターの初期化は、他のパラメーターの初期化に対して不確定に順序付けられます。

これは、あなたの例では、次のステップが順番に行われることを意味します。

  • f評価されます。
  • xが評価され、のパラメータfが初期化されます。
  • 関数呼び出しf(x)が評価されます。
  • f(x)->g評価されます。
  • argsおよびのその他の引数gが評価され、のパラメータgが初期化されます(指定されていない順序で)。
  • 最後に、関数呼び出しf(x)->g(args, ...)が評価されます。
于 2013-03-01T22:36:53.893 に答える
4

注意してください、あなたはあなたのタイトルで1つの質問をしていて、あなたの質問の本文で別の質問をしていると思います。

まあ、それは本当に矛盾していません。関数を評価するには、次のことが発生する必要があります(必ずしもこの順序である必要はありません)。

  • xが評価されます(A)
  • argsが評価されます(B)
  • ...評価されます(C)
  • f(x)は(D)と呼ばれます
  • f(x)の戻り値がコピーされます(E)
  • return-> g(args、...)は(F)と呼ばれます

さて、あなたが引用したルールは次のことを示しています

  1. (A)は(D)の前に発生する必要があります。これは、評価する前に関数の引数を評価するシーケンスポイントがあるためです。
  2. (D)は(E)の前に発生します。これは、関数が実行されるまでコピーを作成できないためです。
  3. (F)は(E)の後に発生します。これは、g(args)を呼び出すために暗黙のポインターが必要なためです*
  4. (B)と(C)は引数であるため、(F)の前に発生します。

ただし、シーケンスされていないのは、(A)、(B)、および(C)の間の関係、または(B)と(C)と(D)の間の質問です。これらは、(F)の引数ではないためです。それらは後で評価することができます。または、事前に評価することもできます。

*興味深い質問。g(args、...)が静的メンバー関数の場合はどうなりますか。この場合、f(x)から返されたポインターは実際には渡されないので、より早くシーケンスできますか?しかし、それは別の質問です。

于 2013-03-01T22:00:30.600 に答える