web-dev-qa-db-ja.com

C ++でどのように「再割り当て」しますか?

C++でreallocを使用するにはどうすればよいですか?言語にはないようです-newdeleteがありますが、resizeはありません!

私のプログラムがより多くのデータを読み込むにつれて、それを保持するためにバッファを再割り当てする必要があるため、それが必要です。古いポインターをdeleteingし、新しい大きなポインターをnewingするのは正しい選択肢ではないと思います。

77
bodacydo

Type* t = (Type*)malloc(sizeof(Type)*n) 
memset(t, 0, sizeof(Type)*m)

になる

::std::vector<Type> t(n, 0);

それから

t = (Type*)realloc(t, sizeof(Type) * n2);

になる

t.resize(n2);

代わりに、関数にポインターを渡したい場合

Foo(t)

つかいます

Foo(&t[0])

VectorはスマートC配列であるため、絶対に正しいC++コードです。

47
f0b0s

おそらく、std::vectorのように、作業を行うコンテナを使用するのが適切なオプションです。

newおよびdeleteは、指定されたタイプのオブジェクトを保持するのに十分なメモリを割り当てるため、サイズを変更できません。特定のタイプのサイズは変更されません。 new[]delete[]がありますが、それらを使用する理由はほとんどありません。

Cでreallocが行うことは、とにかくmallocmemcpy、およびfreeである可能性がありますが、メモリマネージャーは、もしあれば十分な連続した空きメモリが利用可能です。

45
Thomas

C++でのサイズ変更は、コンストラクターとデストラクターを呼び出す必要があるため、扱いにくいです。

C++で_resize[]_および_new[]_と一緒に使用する_delete[]_演算子を使用できなかった根本的な理由はないと思います。

_newbuf = new Type[newsize];
std::copy_n(oldbuf, std::min(oldsize, newsize), newbuf);
delete[] oldbuf;
return newbuf;
_

明らかにoldsizeは秘密の場所から取得されます。これは_delete[]_にあり、Typeはオペランドの型から取得されます。 _resize[]_は、Typeがコピー可能でない場合に失敗します-そのようなオブジェクトは単に再配置できないため、正しいです。最後に、上記のコードは、オブジェクトを割り当てる前にデフォルトで構成しますが、これは実際の動作としては望ましくありません。

_newsize <= oldsize_を使用して、新しく縮小された配列の「最後を過ぎた」オブジェクトのデストラクタを呼び出し、それ以外は何もしない最適化が可能です。標準では、この最適化が必要か(resize()ベクトルの場合)、許可されているが指定されていない、許可されているが実装依存、または禁止されるかを定義する必要があります。

次に、あなた自身に問うべき質問は、「vectorが提供することを考えると、実際にこれを提供することは有用であり、特に連続メモリのサイズ変更可能なコンテナを提供するように設計されています。 C++ 98ですが、C++ 03で修正されました)これは、C++の方法で配列よりも適していますか?」

答えは広く「いいえ」と考えられていると思います。 Cの方法でサイズ変更可能なバッファーを使用する場合は、C++で使用可能な_malloc / free / realloc_を使用します。サイズ変更可能なバッファをC++の方法で処理する場合は、ベクトルを使用します(実際に連続したストレージが必要ない場合はdequeを使用します)。ベクトルのようなコンテナを実装している場合を除き、生のバッファに_new[]_を使用して2つを混合しようとしないでください。

33
Steve Jessop