0

intポインターの配列のサイズを変更したい場合、次のような関数があります。

    template<typename T>
static void Resize(T* arr, UINT oldsize, UINT newsize) {
    T* ret = new T [newsize];
    memcpy(ret, arr, sizeof(arr[0]) * oldsize);
    delete[] arr;   
    arr = ret;
};

「new」キーワードで作成された要素の配列のサイズを変更しようとすると、問題が発生します(クラス内のデータ自体はPODですが)。delete[]はデコンストラクターをトリガーし、新しい配列にポインターを残します。もう存在しないオブジェクト。つまり、オブジェクトが「new」で作成されたとしても、freeコマンドを使用して古い配列を削除することはできませんか?または、各メンバーのデコンストラクターをトリガーせずに、どういうわけか配列を削除しますか?

4

3 に答える 3

4

を使用しstd::vectorます。


編集:一般的な要求により、OPのコードが機能しない理由の説明。

コード:

template<typename T>
static void Resize(T* arr, UINT oldsize, UINT newsize) {
    T* ret = new T [newsize];
    memcpy(ret, arr, sizeof(arr[0]) * oldsize);
    delete[] arr;   
    arr = ret;
};

これが値によって渡さarrれるポインタです。最後にに割り当てるとarr、実際の引数のローカルコピーのみが更新されます。したがって、この後、呼び出し元のコードの実際の引数は、deletedである配列を指しますが、これはかなり壊滅的な結果です。

参照によってそのポインタを渡すことによって、一種の救済になる可能性があります。

template<typename T>
static void Resize(T*& arr, UINT oldsize, UINT newsize) {
    T* ret = new T [newsize];
    memcpy(ret, arr, sizeof(arr[0]) * oldsize);
    delete[] arr;   
    arr = ret;
};

しかし、これはまだかなり壊れやすいコードです。

たとえば、呼び出し元は配列サイズを追跡する必要があります。

std::vector呼び出されるaと、サイズ変更の呼び出しは代わりに次のようになります。

a.resize( newSize )

また、DIYソリューションとは対照的に、newSizeが大きい場合、ベクトルのこれらの余分な要素はnullになります(これは、不確定な値として残すよりも少し安全です)。

Astd::vectorは、生の配列と同じようにインデックスを付けることができます。使用方法の詳細については、 C++の教科書を参照してください。C ++の教科書をまだお持ちでない場合は、入手してください。ほとんどの人にとって、Web上の記事やQ/AからC++を学ぶことは非現実的な提案です。

于 2012-11-28T23:32:26.213 に答える
2

価値のあることとして、あなたがやろうとしていることはひどく悪いことではなく、それが理にかなっていることもありますが、それは単にnewand delete(またはnew[]and delete[])によって提供されるインターフェースによってサポートされていません。他の人が言っているように、それmalloc、、、freeおよびによってサポートされています(再割り当て時にポインタ値をコピーreallocするという警告がreallocありますが、新しい領域のポインタがなどの有用なものに初期化されることを保証するものではありませんNULL)。

したがって、これ以上苦労することなく、ほとんどすべての人に役立つ最も簡単な答えは、std::vector<int>自分でメモリを管理しようとするのではなく、使用することです。ベクトルにはサイズを変更する機能があり、サイズを変更すると、コピーが必要なものがコピーされます。 std::vector「サイズ変更可能なアレイ」を提供し、メモリを管理するために存在します。実際、ポインターのコンテナーが必要な場合は、std::vector<std::unique_ptr<T>>/ std::vector<std::shared_ptr<T>>(C ++ 11の場合)またはBoostPointerContainerいずれかを使用することをお勧めします。

その価値については、元のSTLはを使用new[]またはdelete[]実装していませんでしstd::vector<T>た。多くの場合、オペレーティングシステムはあなたが要求するよりはるかに多くのメモリを提供します。たとえば、malloc16バイトにしようとすると、返されるブロックは1024バイトになる可能性があります。これを使用して、4つの32ビット整数を格納できます。スペースが足りなくなると、32バイトを要求し、1024バイトの別のブロックを取得する場合があります。これに4つの整数をコピーできます。しかし、元のブロックが実際には十分に大きいのに、なぜ整数を保持するための新しいブロックを要求するのに苦労するのでしょうか。残念ながら、「少なくともこれだけの大きさのブロックをください。ちなみに、すでに十分な大きさのブロックがあります」と言う方法を提供しないでください new[]。ある種のことです。 delete[]reallocFacebook Follyには、std::vectornew[]またはを使用しない-likeコンテナーdelete[]が含まれており(通常、オブジェクトのコンテナーでは機能しないため、どちらも使用しないことに注意してくださいrealloc。代わりにmalloc、非標準関数を使用しますmalloc_usable_size)、Firefoxは通過します。同様の方法でメモリを管理する問題。

それでも、トリッキーになろうとするのはお勧めしません。 std::vector満足しているユーザーがたくさんいます。

于 2012-11-29T00:18:56.290 に答える
1

削除する前に配列内のすべての要素がNULLを指すようにすることで、うまくいくと思います。しかし、STLを使用できる場合は、std :: vectorを使用すると、作業がはるかに簡単になります(Alfが提案したように:P)。

于 2012-11-28T23:55:09.900 に答える