0

この質問に基づく:可変サイズタイプの割り当て

次は動作しますか?

{
    // size calculated.
    std::auto_ptr<Base> p(new((void*)(new char[size])) Packet());

    // Do Stuff
}

パケットはPOD構造体であり、最後のメンバーは配列です。動的なサイズの配列を許可するというアイデア(何年も前にCで行っていたように)

struct Packet
{
    // STUFF
    int  data[1];
}
4

2 に答える 2

2

いいえ、これは機能しません。明示的に破棄する必要があり、メモリが個別に処理されるnew以外の、任意の形式の追加パラメータで構築されたオブジェクト:std::nothrow

void* memory = operator new(size);
T* ptr = new(memory) T(args);
...
ptr->~T();
operator delete(memory);

また、生のメモリを割り当てる方法は次のようなものではないことに注意してください。これは、破棄する必要のあるオブジェクトをメモリ内にnew char[size]構築します。char組み込み型では構築も破棄も実際には何もしないことを認識していますが、実装は何かを実行することを許可されており、私が知る限り、これらのデストラクタをスキップする許可はありません。

最後に、オブジェクトも作成する必要がintあり、実装では構造の見かけの終わりの後に何かを置くことができることに注意してください。

于 2012-03-15T07:04:25.193 に答える
1

質問に暗示されている重要な点を見逃してしまい、それが見当たらない場合は、お詫び申し上げます。しかし、この中心線に関して:

std::auto_ptr<Base> p(new((void*)(new char[size])) Packet());

これは私がそれについて言うことができると思うことです:

  1. 最後のコンストラクター呼び出しは、PacketではなくPacket()、である必要がありますが、実際にはコンパイラーはそれをそのまま受け入れる可能性があり、違いはない可能性があります

  2. 内部割り当てnew char[size]では、配列アロケータを使用しますnew []CPPリファレンスは次の式について述べていますnew [array_n]

コンパイラによってエンコードされた追加情報(配列内のオブジェクトを適切に破棄するためにこの情報が必要なため、配列のサイズなど)が原因で、size_of(type)*array_nより多くが割り当てられる場合があることに注意してください。

ここで、外部アロケータ呼び出し、は、配置newnew ((void*)(...))のインスタンスであり、ここでは次のように説明されています。

void* operator new ( std::size_t, void* ptr ); 何もせず、ptrを返します。

つまり、呼び出すnew []と、コンパイラが配列で厳密に必要とされるよりも多くのメモリを割り当て、サイズ関連の情報を余分なスペースにエンコードする場合があります。ただし、新しい配置は「何も」行わないため、いかなる方法でも処理したり、余分な情報を削除したりすることはありません。

ただし、の使用は、を使用して(ではなく)を使用して割り当て解除が実行されることをstd::auto_ptr意味するため、余分な情報が適切に割り当て解除されず、メモリリークまたはさらに悪い結果が生じる可能性があります。delete delete []

編集: CPP参照のみに依存することを避けるために、C++標準N3337の関連部分は次のとおりです。

  • §18.6.1.2は、deleteによって割り当てられたスペースの割り当てを解除するためにのみ使用されnew、それに応じdelete []てによって割り当てられたスペースに使用されると述べていますnew []
  • §18.6.1.3は、配置フォームがアクションを実行しないことを明示的に示してnewnew []ます。これは、どちらも単一オブジェクト空間を配列空間に「変換」するために使用できないことを意味します。

おそらく本当の問題は、質問で新しく提案された配置の適用が、delete []後でスペースの割り当てを解除するためにのみ使用された場合に有効であるかどうかです。おそらく答えは未定義です(これは「いいえ」と同等と解釈されるべきです)。

于 2012-03-15T14:37:09.863 に答える