Помогите, пожалуйста, разобраться в одном вопросе. В C++ нужно создать массив, который бы динамически увеличивался во время выполнения программы. Т.е. мне изначально неизвестно, какого размера он будет. По мере чтения какого-то файла я буду постепенно увеличивать и заполнять этот массив.

Допустим, пишу так:

int *A = new int[1];

Дальше инициализирую несколько элементов чем-нибудь. К примеру:

A[0] = 5;
A[1] = 25;
A[2] = 47;


Затем могу спокойно обращаться к этим элементам, компилятор не ругается. Так можно делать? Я же не задавала нигде размер. Он сам автоматически увеличивается по мере надобности? Или здесь что-то не так?

Или может лучше делать так: создают массив из N элементов. Как только весь заполняется, создаю новый, в 2 раза больше, и копирую в него старый?

@темы: Вопрос, C++

Комментарии
15.03.2011 в 20:01

Нет, все сложнее в C++.

Есть два типа массивов — статические и динамические.
Статические:
int st_arr[15];

Динамические:
int *din_arr = new int[15];

Статические массивы создаются на этапе компиляции. Соответственно, на этапе компиляции нужно знать их размер. Размер динамических массивов можно вычислить в процессе выполнения.
Но ни один из них не подходит (в базовой реализации) для ваших целей. Вам стоит использовать, например, стандартный контейнер std::vector.

#include

int main() {
   std::vector vect;
   vect.push_back(5); // Добавить в вектор целое число 5
   vect.push_back(25); // Добавить в вектор целое число 25
   vect.push_back(vect[0]); // Добавить в вектор значение vect[0], т.е. снова целое число 5
}


Работа с ним, во многом, похожа на работу с массивом. При добавлении новых элементов, когда это необходимо, он сам наращивает свой размер, т.е. то, что вам нужно.
Если нужно подробнее разобраться, советую погуглить "статические массивы c++", "динамические массивы c++" и "vector c++".
15.03.2011 в 20:18

I'm not dead... yet.
> Затем могу спокойно обращаться к этим элементам, компилятор не ругается. Так можно делать? Я же не задавала нигде размер.

Так делать нельзя. Вы динамически выделили память под массив из одного элемента. Вы обращаетесь к второму или двадцать второму элементу массива. Что при этом происходит? Доступ к неправильной ячейке памяти. Которая не выделена для вашей программы. Эта ячейка может быть защищена от записи или иметь какое-то другое назначение. В общем, система поведет себя непредсказуемо. Хотя если компилить в Release, то 99% что программа просто упадет.

> Или может лучше делать так: создают массив из N элементов. Как только весь заполняется, создаю новый, в 2 раза больше, и копирую в него старый?
Вот это будет более правильное поведение. Но если работа делается не в учебных целях, то проще воспользоваться классом наподобие std::vector, который будет выполнять эти действия за вас.
15.03.2011 в 22:19

Спасибо за советы.
Это действительно для реальной программы. Просто меня сбило с толку, что в 1-м случае я не выделяю память под элементы, но нормально их инициализирую и потом обращаюсь с ним. Хотелось понять, в чем подвох.
Тип int я написала просто для примера. На самом деле там дожен быть пользовательский тип struct. То есть массив объектов типа struct с несколькими полями разных типов. Так что вектор, похоже, здесь не подойдет.
Пойду, поищу что-нибудь на Гугле.
15.03.2011 в 22:52

На свете есть всего 10 разновидностей людей. Те, которые понимают бинарный код, и те, кто не понимают
Лучше всего подойдет упомянутый выше vector, работать с ним довольно просто. Но он опять же стандартный. В реальной программе почти всегда лучше использовать стандартное решение.

Но если хотите для себя разобраться, как это работает, поищите задания к лабораторным работам, где надо сделать класс, представляющий собой массив переменной длины. Вполне стандартная задача для студентов на классы :)
15.03.2011 в 23:06

Лучше всего подойдет упомянутый выше vector, работать с ним довольно просто.
Похоже на то )

Нашла еще вот такой пример.

struct TMyStruct
{
int ID;
int Number;
};

TMyStruct* Array=0;
int ArraySize=5;

//создаём массив структур
//malloc выделит необходимое количество динамической памяти
Array=(TMyStruct*)malloc(sizeof(TMyStruct)*ArraySize);

//обращение к массиву
Array[0]=Array[2];
Array[3].ID=7;

//изменения размера массива, при этом, все данные в массиве сохраняются
ArraySize=20;
Array=(TMyStruct*)realloc(Array, sizeof(TMyStruct)*ArraySize);


Очень похоже на мою задачу.
15.03.2011 в 23:12

На свете есть всего 10 разновидностей людей. Те, которые понимают бинарный код, и те, кто не понимают
Sumaya
это Сишный способ, а не плюсовый) потому придется и дальнейшую работу с памятью строить как в С.
15.03.2011 в 23:22

alba-longa
Спасибо, а то я бы могла долго мучиться :bricks:
Значит попробую вектор.
16.03.2011 в 06:44

Sumaya
vector - это шаблон. То, что написано в угловых скобках - это тип элементов вектора.
т.е. если у вас есть какой-то свой тип данных myData вам достаточно написать
std::vector vect;

И это создаст вектор, где каждый его элемент будет иметь нужный вам тип.
16.03.2011 в 19:45

Я уже разобралась с этим, спасибо :)