言ってみましょう、私は持っています
int *p;
p = new int[5];
for(int i=0;i<5;i++)
*(p+i)=i;
次に、配列に 6 番目の要素を追加します。どうすればいいのですか?
配列を再割り当てし、データをコピーする必要があります。
int *p;
p = new int[5];
for(int i=0;i<5;i++)
*(p+i)=i;
// realloc
int* temp = new int[6];
std::copy(p, p + 5, temp); // Suggested by comments from Nick and Bojan
delete [] p;
p = temp;
それはいけません。これには、STL ベクトルなどの動的コンテナーを使用する必要があります。または、より大きな別の配列を作成し、最初の配列からデータをコピーすることもできます。
その理由は、配列がメモリ内の連続した領域を表すためです。上記の例では、p がアドレス 0x1000 を指し、5 つの int が 20 バイトに対応するため、配列は 0x1014 の境界で終了するとします。コンパイラは、0x1014 から始まるメモリに他の変数を自由に配置できます。たとえば、int i
0x1014..0x1018 を占める場合があります。さらに 4 バイトを占有するように配列を拡張すると、どうなるでしょうか?
を使用して初期バッファを割り当てると、malloc
を使用realloc
してバッファのサイズを変更できます。-ed バッファーrealloc
のサイズ変更には使用しないでください。new
int * array = (int*)malloc(sizeof(int) * arrayLength);
array = (int*)realloc(array, sizeof(int) * newLength);
ただし、これは C っぽいやり方です。の使用を検討する必要がありますvector
。
ソースを調べてみませんvector
か?このメカニズムの実装は、C++ インクルード ファイルが存在するフォルダーで確認できます。
gcc 4.3.2 での動作は次のとおりです。
ベクターのアロケーターを使用して、新しい連続したメモリのチャンクを割り当てます (ベクターが ? であることを覚えていvector<Type, Allocator = new_allocator>
ます)。デフォルトのアロケータはoperator new()
(! だけでなくnew
) このチャンクを割り当てるために呼び出しnew[]
ますdelete[]
。
既存の配列の内容を新しく割り当てられた配列にコピーします。
以前に整列されたチャンクをアロケータで破棄します。デフォルトのものは を使用しますoperator delete()
。
(独自のベクトルを作成する場合、サイズは「固定量」ではなく「M 倍」に増加する必要があることに注意してください。これにより、償却された定数時間を達成できます。たとえば、サイズ制限により、ベクトルが 2 倍になり、各要素が平均して 1 回コピーされます。)
他の人が言っているのと同じですが、配列のサイズを頻繁に変更する場合、1 つの戦略はサイズを 2 倍にして毎回配列のサイズを変更することです。常に新しいものを作成し、古いものを破壊するには費用がかかるため、倍増理論では、将来の要素にも十分な余地を確保することで、この問題を軽減しようとします。