Скажем, у меня есть
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;
Теперь я хочу добавить в массив 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, а пять ints соответствуют 20 байтам, поэтому массив заканчивается на границе 0x1014. Компилятор может размещать другие переменные в памяти, начиная с 0x1014; например, int i
может занимать 0x1014..0x1018. Если вы затем расширили массив так, чтобы он занял еще четыре байта, что произойдет?
Если вы выделяете исходный буфер с помощью malloc
, вы можете использовать realloc
для изменения размера буфера. Вы не должны использовать realloc
для изменения размера буфера new
-ed.
int * array = (int*)malloc(sizeof(int) * arrayLength);
array = (int*)realloc(array, sizeof(int) * newLength);
Однако это C-ish способ делать что-то. Вы должны использовать vector
.
Почему вы не смотрите в источники, как это делает vector
? Вы можете увидеть реализацию этого механизма прямо в папке, где хранятся ваши файлы на С++!
Вот что он делает на gcc 4.3.2:
Выделите новый непрерывный кусок памяти с помощью векторного распределителя (вы помните, что этот вектор равен vector<Type, Allocator = new_allocator>
?). Распределитель по умолчанию вызывает operator new()
(а не только new
!), Чтобы выделить этот кусок, позволяя себе не путаться с new[]
/delete[]
stuff;
Скопировать содержимое существующего массива в только что выделенный;
Утилизируйте ранее выровненный блок с распределителем; по умолчанию используется operator delete()
.
(Обратите внимание, что если вы собираетесь писать свой собственный вектор, ваш размер должен увеличиваться "М раз", а не "по фиксированной сумме". Это позволит вам получить амортизированное постоянное время. Например, если каждый отступ от ограничения размера, ваш вектор растет дважды, каждый элемент будет скопирован в среднем один раз.)
То же, что говорят другие, но если вы часто изменяете размер массива, одной стратегией является изменение размера массива каждый раз за счет удвоения размера. Там расходы на постоянное создание новых и уничтожение старых, поэтому теория удвоения пытается смягчить эту проблему, гарантируя, что есть достаточно места для будущих элементов.