1

何をしようとしているのか聞かないでください。これは簡単なテストであり、新しい配置に問題があるかどうかを確認することが唯一の目的です。

問題を見つけた、または何かを誤解しただけです。

#include <vector>

using namespace std;

#define WORKS 
int main(int argc, char** argv) {
    vector<int>* pp = (vector<int>*)malloc(sizeof(vector<int>)*20);

#ifdef WORKS
    for(int i = 0; i < 20; ++i)
    new (pp+i) vector<int>;
#else
    new (pp) vector<int>[20];
#endif

    for(int i = 0; i < 20; ++i) 
        pp[i].~vector<int>();

}

「#define WORKS」を削除すると、次のようなアクセス違反が発生します

    for(int i = 0; i < 20; ++i)
    new (pp+i) vector<int>;

これはうまく機能しますが、

    new (pp) vector<int>[20];

これが破棄段階で例外をスローする原因です。何が起きてる?私は Windows XP で作業しており、VC++ Express 2010 でビルドしています。

4

3 に答える 3

10

§5.3.4/12:

--new T[5]呼び出しの結果operator new[](sizeof(T)*5+x)

[ ... ]

ここで、x と y は、配列割り当てのオーバーヘッドを表す非負の未指定値です。new-expression の結果は、演算子 new[] によって返される値からこの量だけオフセットされます。このオーバーヘッドは、ライブラリ関数演算子 new[](std::size_t, void*) およびその他の配置割り当て関数を参照するものを含む、すべての配列 new 式に適用される可能性があります。オーバーヘッドの量は、new の呼び出しごとに異なる場合があります。【強調追記】

要約すると、配列を配置しようとすると、割り当てていない不特定の量のオーバーヘッドが必要になる場合があります。要素を個別に配置する限り、そのようなオーバーヘッドは許可されないため、新しい配置が機能します。

于 2011-04-19T20:05:16.857 に答える
1

新しい式の結果は、配置の新しい演算子に渡されたアドレスと同じである必要はありません。また、配列を割り当てるために必要なサイズが、厳密に1つの要素のサイズに要素の数を掛けたものであるとは限りません。

5.3.4:

new-expressionは、要求されたスペースの量をタイプの最初の引数として割り当て関数に渡します std::size_t。その引数は、作成されるオブジェクトのサイズ以上でなければなりません。オブジェクトが配列である場合にのみ、作成されるオブジェクトのサイズよりも大きくなる可能性があります

したがって、コードのより正しいバージョンは次のようになります。

     void *ppstorage= malloc(sizeof(vector<int>)*20);
    pp= new (ppstorage) vector<int>[20];

    for(int i = 0; i < 20; ++i) 
        pp[i].~vector<int>();

あなたはほぼ確実にの終わりを過ぎて書くでしょうがppstorage。コンパイラは、各要素を適切に破棄するために、配列のカウントをどこかに格納する必要があります。MSVCの場合、新しい式によって返されるアドレスの前に格納されます。

理論的には、オーバーロードoperator new[]して配列の実際の割り当てサイズを取得できます。

void *operator new[](size_t *allocation_size, size_t size)
{
    *allocation_size= size;
    return nullptr;
}

しかし、私はこれを試したことがありません。

于 2011-04-19T19:45:32.787 に答える
0

使用するときoperator new[]は、で割り当てを解除する必要がありますoperator delete[]new[]割り当ててから、1 つずつ割り当てを解除することはできません。したがって、解放ループの代わりに、次のようにします。

delete [] pp;
于 2011-04-20T14:46:45.903 に答える