TL;DR
次のコードがあるとします。
int* ptr;
*ptr = 0;
インダイレクションを適用する前にの左辺値から右辺値への変換が*ptr
必要ですか?ptr
標準は、多くの場所で左辺値から右辺値へのトピックをカバーしていますが、 * 演算子がそのような変換を必要とするかどうかを判断するのに十分な情報を指定していないようです。
詳細
左辺値から右辺値への変換については、N3485のセクション左辺値から4.1
右辺値への変換パラグラフ1で説明されており、次のように述べられています ( employment mine going forward ):
非関数型、非配列型 T の glvalue (3.10) は prvalue に変換できます。glvalue が参照するオブジェクトが T 型のオブジェクトではなく、T から派生した型のオブジェクトでもない場合、またはオブジェクトが初期化されていない場合、この変換を必要とするプログラムの動作は未定義です .[...]
それで*ptr = 0;
、この変換が必要ですか?
4
セクションパラグラフ1に行くと、次のように書かれています。
[...]必要に応じて、式を 必要な変換先の型に変換するために、標準の変換シーケンスが式に適用されます。
では、いつ必要なのですか?セクション5
Expressionsを見ると、左辺値から右辺値への変換はパラグラフ9で言及されています。
glvalue 式が、そのオペランドの prvalue を予期する演算子のオペランドとして現れるときはいつでも、左辺値から右辺値へ (4.1)、配列からポインターへ (4.2)、または関数からポインターへ (4.3) の標準変換が行われます。式を prvalue に変換するために適用されます。[...]
そしてパラグラフ11には次のように書かれています:
一部のコンテキストでは、式はその副作用のためにのみ表示されます。このような式は破棄値式と呼ばれます。[...] 左辺値から右辺値への変換 (4.1) は、式が volatile 修飾された型の左辺値であり、次のいずれかである場合にのみ適用されます [ ...]
どちらの段落もこのコード サンプルには適用されないようで、5.3.1
単項演算子の段落1には次のように書かれています。
単項 * 演算子は間接参照を実行します。それが適用される式は、オブジェクト型へのポインター、または関数型へのポインターであり、結果は、式が指すオブジェクトまたは関数を参照する左辺値になります。式の型が「T へのポインタ」の場合、結果の型は「T」になります。[ 注: 不完全な型 (cv void 以外) へのポインタによる間接化は有効です。このようにして得られた左辺値は、限られた方法で使用できます (たとえば、参照を初期化するため)。この左辺値は、prvalue に変換してはなりません。4.1 を参照してください。—終わりのメモ]
ポインターの値を必要としないようで、ポインターの変換の要件が見当たりません。何か不足していますか?
なぜ私たちは気にするのですか?
インダイレクションを適用する前に左辺値から右辺値への変換が必要なため、初期化されていないポインターの使用は未定義の動作であると主張する他の質問の回答とコメントを見てきました。ptr
例: C++ 標準は、初期化されていないポインターの逆参照が未定義の動作であると正確にどこで言っていますか? はこの議論を行っており、標準の最近のドラフト バージョンのいずれにも示されている内容と議論を一致させることはできません。私はこれを数回見たので、明確にしたいと思いました。
上記のリンクされた質問で指摘したように、未定義の動作に到達する他の方法があるため、未定義の動作の実際の証明はそれほど重要ではありません。