Динамическое выделение памяти для изменения размера массива, начиная с неизвестного размера C++

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

Я знаю, что для выделения памяти это

int count;
int *n = new int[count];

Скажем, переменная count будет увеличиваться в цикле. Как изменить размер массива?

Кроме того, что, если бы мы сделали это с помощью malloc?


person user2159166    schedule 04.10.2014    source источник
comment
Вам придется удалить вектор n и создать новый большего размера. И нет смысла использовать malloc, если можно использовать new.   -  person Javi    schedule 04.10.2014
comment
См. пример realloc: cplusplus.com/reference/cstdlib/realloc   -  person Ashalynd    schedule 04.10.2014
comment
@JaviV За исключением того, что malloc может поддерживать realloc, тогда как для new нет эквивалента.   -  person Neil Kirk    schedule 04.10.2014
comment
почему бы не использовать вектор?   -  person pqnet    schedule 04.10.2014
comment
Должен ли я инициализировать count равным 0?   -  person user2159166    schedule 04.10.2014


Ответы (3)


Не пытайтесь сделать так, чтобы распределение массива точно соответствовало постоянно меняющимся требованиям к размеру того, что вы собираетесь хранить. Рассмотрите возможность использования традиционного множителя 2*N. Когда массив заполнен, перераспределите его, увеличив на 2*N (выделите новый массив в два раза больше) и скопируйте элементы. Это логарифмически амортизирует стоимость перераспределения.

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

Но если вы настроены на это, продолжайте считать кратное 2, начиная с чего-то реалистичного (или ближайшего кратного 2, округленного).

person codenheim    schedule 04.10.2014
comment
Значит ли это, что мне придется создавать много массивов, так как мне нужно копировать элементы? - person user2159166; 04.10.2014
comment
Или я могу скопировать в один массив, а затем освободить первый массив, затем снова перераспределить и скопировать в старый массив и освободить новый массив? Так что в основном просто используйте только два массива? - person user2159166; 04.10.2014
comment
Не делайте ничего хорошего, чтобы удерживать старый, единственный раз, когда вы перераспределяете, это когда вы перерастаете массив, поэтому вы всегда двигаетесь вверх, а не вниз. Как только массив растет, на самом деле нет никаких преимуществ в уменьшении размера, просто оставьте все как есть. - person codenheim; 05.10.2014
comment
Нет, после изменения размера, как только вы скопируете элементы в новый массив, удалите старый. - person codenheim; 05.10.2014
comment
И это один конкретный случай использования, когда вы имеете право использовать malloc/realloc для хранения массива. Во-вторых, убедитесь, что все это инкапсулировано в классе. Класс должен иметь текущий размер и указатель массива. - person codenheim; 05.10.2014
comment
Не могли бы вы привести пример? - person user2159166; 05.10.2014

Вы можете сохранить два указателя, p и q (заполнитель), при изменении счетчика вам нужно выполнить новое выделение для p, прежде чем нужно будет освободить более ранние выделения, даже до того, как содержимое более раннего p должно быть перенесено в новый p также.

int count, oldcount;
int *p = NULL;
int *q;
p = new int[count];
oldcount = count;

когда вам нужно перераспределить:

q = new int[count];
memcpy(q, p, oldcount * sizeof(int)); // OR for (int i = 0; i < oldcount; i++) q[i] = p[i];   
delete [] p;
p = q;
oldcount = count; // for use later

Если вы используете malloc, calloc тогда вам нужно использовать как количество байтов для передачи в malloc. но не требуется с операторами new и delete в C++

person Dr. Debasish Jana    schedule 04.10.2014
comment
@JaviV спасибо, отредактировал мой ответ, а также спасибо Wyzard - person Dr. Debasish Jana; 04.10.2014

Как изменить размер массива?

Использование new: Вы не можете. Размер объекта (здесь объект массива) не может измениться во время выполнения.

Вам нужно будет создать новый массив соответствующего размера, скопировать все элементы из старого в новый массив и уничтожить старый. Чтобы избежать многих перераспределений, вы всегда должны выделять больше, чем вам нужно. Следите за size (количество элементов, используемых в настоящее время) и capacity (фактический размер выделенного массива). Если вы хотите увеличить size, проверьте, осталась ли еще память (size<capacity), и используйте ее, если возможно; в противном случае примените вышеупомянутый метод.

И это именно то, что vector делает для вас: Но с RAII и всеми возможными удобствами.

person Columbo    schedule 04.10.2014
comment
На самом деле realloc не всегда перемещает блок памяти. Если после перераспределяемого блока доступно достаточно непрерывной памяти, то блок не перемещается. Если блок должен быть перемещен, realloc выполняет копирование... Так что не всегда нужно выделять новую память и копировать - person ds27680; 04.10.2014
comment
@ ds27680 Мы говорим не о malloc/realloc, а о new. - person Columbo; 04.10.2014
comment
На самом деле он спросил, как динамически выделить массив, размер которого обязательно изменится. В качестве примера он привел новый (то, как он знает, может быть выполнено распределение). Ваш ответ, как я его прочитал, будет означать, что вам всегда нужно выделять новые и копировать. Вы не упомянули, что имеете в виду только новое, когда говорите: «Вы не можете». - person ds27680; 04.10.2014
comment
Он также спросил в конце своего вопроса. Кроме того, что, если бы мы сделали это с помощью malloc? Так что его вопрос явно не только о new, но и о malloc. Хотя ваш ответ создает впечатление, что то, что вы говорите, в целом применимо. - person ds27680; 04.10.2014
comment
@ ds27680 О, я не видел часть про malloc. - person Columbo; 04.10.2014