未定義の動作とシーケンスのポイント: 詳しい説明
式 i = i;未定義動作 (UB) を呼び出すとラベル付けされていますが、提供されている Index クラスのように、i の型がユーザー定義である場合はどうなりますか?
ユーザー定義型と UB
Index のようなユーザー定義型の場合、式 i = i;は依然として UB とみなされます。これは、ユーザー定義型がインクリメント演算子のデフォルトの動作をオーバーライドしないためです。演算子 () 関数と演算子 =() 関数は、Index オブジェクトの内部状態を変更するだけであり、シーケンス ポイントは作成しません。したがって、式は連続するシーケンス ポイント間でオブジェクトを 2 回変更し、UB になります。
式の等価性
式 i.operator =(i.operator () );そして i.add(i.inc());は元の i = i; と同等ではありません。最初の式では、i.operator () の評価後のシーケンス ポイントにより、= 演算子の評価前に Index オブジェクトを変更できます。同様に、2 番目の式では、メンバー関数 add および inc は、連続するシーケンス ポイント間のオブジェクトを変更しません。したがって、これらの式は UB を呼び出しません。
式の定義とシーケンス ポイント
式 i = i;確かに式ですが、その動作は明確に定義されていません。式に関連付けられたシーケンス ポイントの数は、関係するオペランドのタイプには依存しません。
配列の添字 (a[ i] = i)
式 a [ i] = i; a が組み込み型の配列である場合、または a が添え字演算子をオーバーロードするユーザー定義型である場合の両方の場合でも、 は UB になります。どちらの場合も、[ i] 式が最初に評価され、i がインクリメントされ、事前にインクリメントされた値が返されます。この値は配列のインデックスとして使用され、インデックスが範囲外の場合は UB が発生する可能性があります。
複数のインクリメント演算 ( i)
式 i;は C 03 で明確に定義されており、式 ((((i.operator ()).operator ()).operator ()).operator ()).operator ()); と同じ動作をします。各演算子 () の呼び出しは Index オブジェクトへの参照を返し、各関数評価後のシーケンス ポイントにより、連続するシーケンス ポイント間でオブジェクトが 1 回だけ変更されることが保証されます。
結論
要約すると、式 i = i;そして a[ i] = i;型がオーバーロードされた演算子を提供する場合でも、ユーザー定義型に対して UB を呼び出します。 Index オブジェクトに対する複数のインクリメント操作は明確に定義されており、シーケンス ポイントとシーケンス ポイント間のオブジェクトへの変更の数が、関係するオペランドの種類に依存しないことが示されています。
以上がユーザー定義型でも「i = i;」は未定義の動作ですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。