未定義の動作の再検討: シーケンス ポイントとユーザー定義型
質問:
未定義の動作とシーケンス ポイントに関する前回の記事では、式 i = i は組み込み型に対して未定義の動作を呼び出すと見なされます。ただし、i の型がユーザー定義の場合はどうなるのかという疑問が生じます。具体的には、オーバーロードされた演算子を含むクラス Index があるとします。
答え: 未定義の動作と適切に定義された動作
直感に反して、式 i = i は、Index などのユーザー定義型に対して未定義の動作を引き起こしません。これは、Index 内のオーバーロードされた演算子が関数とみなされるためです。 C ISO 標準によれば、関数の評価では、関数の引数の評価後にシーケンス ポイントが導入され、戻り値のコピー後に別のシーケンス ポイントが導入されます。
シーケンス ポイントとオーバーロードされた演算子
i = i の場合、式 i は演算子 = に引数として渡される前に評価されます。これは、i の評価後にシーケンス ポイントが存在し、連続するシーケンス ポイント間でオブジェクト i が 1 回だけ変更されることを保証することを意味します。
したがって、Index のようなユーザー定義型の式 i = i は等価です。これは、未定義の動作がない明確に定義された式です。同じことが構文的に単純な式 i.add(i.inc()); にも当てはまります。
微妙な違い:
i = であることに注意することが重要です。 i は、C 文法の意味での式ではありません。代わりに、これは式とステートメントを構文的に組み合わせた「ステートメント式」です。ステートメント式は通常のステートメントとして実行されますが、その結果を変数に割り当てることもできます。
a[ i] = i
の動作 a が配列の場合組み込み型の式 a[ i] = i は、左辺値 a[ i] が 2 回 (式 i で 1 回、代入 i で 2 回) 評価されるため、未定義の動作を呼び出します。 = i.
ただし、 a が添字演算子をオーバーロードするユーザー定義型の場合、式は添字演算子の実装に応じて異なる動作をする可能性があります。たとえば、添え字演算子が const Index& 演算子[](Index i) を使用して実装されている場合、左辺値 a[ i] は添え字演算子が呼び出される前に 1 回だけ評価されるため、式は適切に定義されます。
i の有効性;
式 i;これは ((i.operator ()).operator ()).operator () と同等であるため、C 03 で明確に定義されています。これは、各演算子がシーケンス ポイントを導入し、連続するシーケンス ポイント間でオブジェクト i が 1 回だけ変更されるようにするためです。
以上が`i = i` は C のユーザー定義型で未定義の動作を呼び出しますか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。