単純なデフォルトコンストラクターがアクションを実行しない場合、mallocを使用して単純な構成可能なオブジェクトを作成できないのはなぜですか?


14

単純なデフォルトコンストラクターについて、cppreferenceから引用された次の段落を理解するのが困難です。私はstackoverflowを検索しましたが、それでも明確な答えが得られませんでした。助けてください。

単純なデフォルトコンストラクターは、アクションを実行しないコンストラクターです。C言語と互換性のあるすべてのデータ型(POD型)は、簡単にデフォルトで構築できます。ただし、Cとは異なり、単純なデフォルトコンストラクターを持つオブジェクトは、std :: mallocで割り当てられたメモリなど、適切に配置されたストレージを単に再解釈することによって作成することはできません。

具体的には、自明なデフォルトコンストラクターが何もしない場合、ストレージを再解釈して、指定されたタイプのオブジェクトがあるふりをすることができないのはなぜですか?これにより発生する可能性のある未定義の動作の例をいくつか教えていただけますか?


コンパイラの最も重要な仕事は、ソースコードをコンパイルすることではなく、無効な可能性のあるコードを拒否することです。malloc()を使用する場合、これを行うことはできません。
Hans Passant

6
理由は非常に簡単です。プログラマーがクレイジーなことをする機会が少ないほど、コンパイラーがクレイジーなこと(積極的な最適化)をする機会が多くなります。
n。「代名詞」m。

1
同様の理由で、あなただけではできません*reinterpret_cast<float*>(&someNonFloatObject) = 0.1f;。C ++にはオブジェクトとオブジェクトの有効期間の概念があり、抽象マシンで指定されます。ストレージからオブジェクトを作成するCPU命令がないからといって、抽象マシンで違いがないということではありません。
Max Langhof

1
@HansPassantすべてのコードを拒否するコンパイラは、すべての無効なコードを拒否します。とにかく、UBのあるプログラムを拒否するのはコパイラーの仕事ではありません。
n。「代名詞」m。

回答:


7

P0593R5はこの例を示します。

struct X { int a, b; };
X *make_x() {
  X *p = (X*)malloc(sizeof(struct X));
  p->a = 1;
  p->b = 2;
  return p;
}

と説明します:

C-++コンパイラーでコンパイルすると、p-> aはXオブジェクトのintサブオブジェクトに書き込もうとし、このプログラムはXオブジェクトもintサブオブジェクトも作成しなかったため、このコードの動作は未定義です。

[intro.object] p1ごと

オブジェクトは、定義、new-expression、共用体のアクティブなメンバーを暗黙的に変更するとき、または一時オブジェクトが作成されるときに作成されます。

...そしてこのプログラムはこれらのことを何もしませんでした。

実際にはこれは機能し、UBの状況は他の何よりも標準の欠陥と見なされます。このペーパーの全体的な目的は、他のことを壊すことなくその問題と同様のケースを修正する方法を提案することです。


1

「純度」の理由から。

代替案と実際の現状では、ストレージのすべての領域に、そのストレージに適合するすべてのオブジェクトが同時に含まれます。一部の委員会メンバーは現状に不安感じており、多くの人々が同じ場所に(仮想の、初期化されていない状態で)無限に多くのオブジェクトを持つことを恐れていました。

ストレージの領域に無限に多くのオブジェクトが存在することで論理的な問題を示すことができた例はありません。

矛盾することを言っている規格の異なるセクションがあったため、委員会のメンバーは規格の最悪の部分の1つを真剣に受け止めることを決定しました。

また、規格の一部を真剣に考えている場合は、文字列リテラルを使用することは厳密に許可されていません。


実際、文字列リテラルの使用は厳密には許可されていませんtype_infoオブジェクトに関して同様のCWG問題があります。「試合の文字列リテラルを報告しましたか?
言語弁護士
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.