私の最初の考えは、それは未定義の振る舞いであるということでした。
5.3.5 / 3:「2番目の選択肢(配列の削除)では、削除するオブジェクトの動的タイプが静的タイプと異なる場合、動作は未定義です。73)。
脚注73には、「これは、型void*
のオブジェクトがないため、型のポインタを使用してオブジェクトを削除できないことを意味します」と書かれていますvoid
。
1.3.3の「動的タイプ」の定義は「最も派生したオブジェクト」に言及し、1.8 / 4の「最も派生したオブジェクト」の定義はオブジェクトについて話しているため、おそらく、この例のオブジェクトには動的タイプがありません。クラスタイプの。だから私は探し続けました:
5.2.10 / 3:「[reinterpret_cast]は、元の値とは異なる表現を生成する場合と生成しない場合があります」
5.3.5 / 2: "のオペランドの値はdelete
、前の配列
new-expressionから得られたポインタ値でなければなりません"。
reinterpret_castが入力されたものと同じポインター値になるかどうかはわかりません。おそらく、私がまだ見つけていない標準の他のビットによってクリアされています。このコードを「OK」と呼ぶのは、ポインターをreinterpret_castすると、結果が以前と同じ「ポインター値」になることを明確に示すものがないため、delete[]に渡すことで「ポインター値」を渡すことになります。 "new[]から。
5.2.10 / 7:「[特定のポインター型間で]キャストして元の型に戻すと元のポインター値が生成されることを除いて、そのようなポインター変換の結果は指定されていません」。
これは私には悪いニュースのように見えます-キャストが同じ値を生成するということではなく、キャストのペアが同じ値を生成するというだけです。これは、単一のキャストが異なる値を生成することを許可されていることを私に示唆していますが、それは示唆的なものであり、明示的ではありません。これは、「標準が動作を記述していない場合、動作は未定義である」というルールの通常の問題です。インデックスを使用して見つけることができる段落のいずれにも記載されていないからといって、他の場所に記載されていないという意味ではありません...
実際には、バイトを検査するためにunsigned char *にキャストしたり、memcpyを使用してPODをコピーするためにvoid *にキャストしたりできるため、エイリアスを作成するためのキャストが保証されている必要があります。実装が特定のキャストでエイリアスを作成する場合は、new[]から取得した「同じ値」を渡していると思うかもしれません。しかし、それがdelete[]に十分かどうかはまだわかりません。重要なことが欠けていると思います。