13

C++のエイリアシング規則のために、char配列に無制限(int *)を指すことができないという合意があるようです。intをchar配列に入れるには、新しい配置が法的に必要ですか?

この他の質問から - Generic char[] based storage and avoiding strict-aliasing related UB - プレースメントを介してストレージを(再)使用することが許可されているようです。

alignas(int) char buf[sizeof(int)]; 

void f() { 
    // turn the memory into an int: (??) from the POV of the abstract machine! 
    ::new (buf) int; // is this strictly required? (aside: it's obviously a no-op) 

    // access storage: 
    *((int*)buf) = 42; // for this discussion, just assume the cast itself yields the correct pointer value 
} 

ので、上記の法律上のC++では実際にそれが法的にするために必要な新しい配置のですか?

+0

関連:http://stackoverflow.com/questions/38862092/is-it-legal-to-alias-a-char-array-through-a-pointer-to-int –

+0

https://godbolt.org/g/k2nVI9 –

+0

関連性の高い、潜在的な詐欺:https://stackoverflow.com/questions/40873520/reinterpret-cast-creating-a-trivially-default-constructible-object –

答えて

12

はい、プレースメントnewが必要です。そうでない場合、厳密なエイリアシング(割り当てはaccess)に違反します。

上記は合法ですか?ほぼ(ほぼすべての実装で動作しますが)ほぼです。キャストによって作成したポインタはオブジェクトを指していません。なぜなら、(今は破壊された)配列とintオブジェクトがpointer-interconvertibleではないからです。 std::launder((int*)buf)を使用するか、より良い方法ですが、配置newの戻り値を使用してください。

+1

厳密なエイリアシングは 'reinterpret_cast (buf)= 42'によって違反されません。新しい' int'オブジェクトに 'int'型の左辺値としてアクセスするからです。ポインタ相互変換は、「死んだ」ポインタから非オブジェクトへのポインタをライブポインタに変換するときではなく、「ライブ」ポインタを別のポインタに変換するときに適用できます。編集:私はそこに 'launder'が必要かどうか分からない。私が知っていた最後のルールは依然として流動的でした。 – Potatoswatter

+1

@Potatoswatterどの新しいintオブジェクトですか?私は、そのようなオブジェクトを作成するための新しいプレースメント・プレースメントがないケースについて話していました。また、私はポインタを再解釈するときに一般的に適用可能なポインタ相互変換機能を読んでいます。それにもかかわらず、キャストを使用してopで作成されたポインタは、P0137で定義されている新しいオブジェクトを指していないので、 'launder'が必要です。 – Columbo

+0

[basic.lval]特定のタイプの左辺値以外のオブジェクトにアクセスすることを禁じます。まだオブジェクトが存在するかどうかの問題は扱いません。 [basic.life]/C++ 14の6では、reinterpret_castを使って生涯を始めることができます。これはP0137によって削除されるので、C++ 17はプレースメントを新しいものにする(おそらく)でしょう。あなたはポインタの相互変換性について正しいです。 P0137は 'void *'から 'static_cast'を介して' reinterpret_cast'に接続します。だから、生きているオブジェクトにアクセスするためには 'launder'が必要です(しかし決して非オブジェクトへの' launder'ストレージはありません)。 – Potatoswatter

-3
*((int*)buf) = 42; 

int左辺値でintを書き込み、そのエイリアシングの問題は最初の場所ではありません。

関連する問題