Как динамически расширять массив на С++? {как в векторе}

Скажем, у меня есть

int *p;
p = new int[5];
for(int i=0;i<5;i++)
   *(p+i)=i;

Теперь я хочу добавить в массив 6-й элемент. Как это сделать?

Ответ 1

Вам необходимо перераспределить массив и скопировать данные:

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;

Ответ 2

Вы не можете. Для этого вы должны использовать динамический контейнер, такой как вектор STL. Или вы можете сделать другой массив, который больше, а затем скопировать данные из вашего первого массива в него.

Причина в том, что массив представляет собой смежную область в памяти. Для вашего примера выше, скажем, что p указывает на адрес 0x1000, а пять ints соответствуют 20 байтам, поэтому массив заканчивается на границе 0x1014. Компилятор может размещать другие переменные в памяти, начиная с 0x1014; например, int i может занимать 0x1014..0x1018. Если вы затем расширили массив так, чтобы он занял еще четыре байта, что произойдет?

Ответ 3

Если вы выделяете исходный буфер с помощью malloc, вы можете использовать realloc для изменения размера буфера. Вы не должны использовать realloc для изменения размера буфера new -ed.

int * array = (int*)malloc(sizeof(int) * arrayLength);
array = (int*)realloc(array, sizeof(int) * newLength);

Однако это C-ish способ делать что-то. Вы должны использовать vector.

Ответ 4

Почему вы не смотрите в источники, как это делает vector? Вы можете увидеть реализацию этого механизма прямо в папке, где хранятся ваши файлы на С++!

Вот что он делает на gcc 4.3.2:

  • Выделите новый непрерывный кусок памяти с помощью векторного распределителя (вы помните, что этот вектор равен vector<Type, Allocator = new_allocator>?). Распределитель по умолчанию вызывает operator new() (а не только new!), Чтобы выделить этот кусок, позволяя себе не путаться с new[]/delete[] stuff;

  • Скопировать содержимое существующего массива в только что выделенный;

  • Утилизируйте ранее выровненный блок с распределителем; по умолчанию используется operator delete().

(Обратите внимание, что если вы собираетесь писать свой собственный вектор, ваш размер должен увеличиваться "М раз", а не "по фиксированной сумме". Это позволит вам получить амортизированное постоянное время. Например, если каждый отступ от ограничения размера, ваш вектор растет дважды, каждый элемент будет скопирован в среднем один раз.)

Ответ 5

То же, что говорят другие, но если вы часто изменяете размер массива, одной стратегией является изменение размера массива каждый раз за счет удвоения размера. Там расходы на постоянное создание новых и уничтожение старых, поэтому теория удвоения пытается смягчить эту проблему, гарантируя, что есть достаточно места для будущих элементов.