Перейти к основному содержимому

Динамические массивы

Динамический массив получает размер во время работы программы

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

Коротко

new[] создаёт массив во время работы программы. delete[] освобождает этот массив. Если забыть delete[], память останется занятой до завершения программы.

Когда это нужно

Пример: пользователь вводит, сколько измерений нужно обработать. До запуска программы это число неизвестно.

#include <iostream>
using namespace std;

int main() {
int n = 0;

cout << "Enter count: ";
cin >> n;

if (n <= 0) {
cout << "bad count" << endl;
return 1;
}

int* a = new int[n];

delete[] a;
return 0;
}

Пока массив создан, указатель a хранит адрес его первого элемента.

Жизненный цикл динамического массива от запроса памяти до освобождения

Заполнение массива

#include <iostream>
using namespace std;

int main() {
int n = 5;
int* a = new int[n];
int i = 0;

for (i = 0; i < n; i++) {
a[i] = i * 10;
}

for (i = 0; i < n; i++) {
cout << a[i] << endl;
}

delete[] a;
return 0;
}

Как и обычный массив, динамический массив нужно заполнить перед чтением. Значения по умолчанию не считаем надёжными.

new[] и delete[] должны совпадать

СоздалиОсвобождаем
new int[n]delete[] a
new intdelete p

Если массив создан через new[], освобождать его нужно через delete[]. Квадратные скобки важны.

Утечка памяти

Плохой пример:

#include <iostream>
using namespace std;

int main() {
int* a = new int[100];

cout << "done" << endl;
return 0;
}

Массив создан, но не освобождён. Это называется утечкой памяти.

Правильно:

#include <iostream>
using namespace std;

int main() {
int* a = new int[100];

cout << "done" << endl;

delete[] a;
return 0;
}

После delete[]

После освобождения старый адрес использовать нельзя.

int* a = new int[3];
a[0] = 10;

delete[] a;
a = nullptr;

Запись a = nullptr; не освобождает память сама по себе. Она только показывает, что этот указатель больше никуда не указывает.

В реальных программах

Ручной new[] полезен для понимания памяти. Но в обычной прикладной программе чаще выбирают vector, потому что он сам управляет памятью. В микроконтроллерных проектах динамическую память используют осторожно: она может усложнить предсказуемость работы.

Практика

  1. Считайте n, проверьте, что оно больше нуля.
  2. Создайте динамический массив из n чисел.
  3. Заполните массив значениями 0, 10, 20 и так далее.
  4. Выведите все элементы через цикл.
  5. Освободите массив через delete[].

Проверьте себя

  1. Чем динамический массив отличается от обычного?
  2. Что возвращает new int[n]?
  3. Почему нужен delete[]?
  4. Что такое утечка памяти?
  5. Почему после delete[] нельзя читать старый адрес?
Ориентиры для самопроверки

Сначала ответьте без подсказки. Ответ можно считать полным, если вы:

  • формулируете основную мысль своими словами;
  • называете важные условия, ограничения или меры безопасности;
  • для схемы, кода или расчёта показываете ход решения и ожидаемый результат.

Если один из пунктов объяснить не получается, найдите соответствующую главу статьи, перечитайте её и повторите ответ.

Словарь статьи

ТерминЗначение
динамическая памятьпамять, запрошенная во время работы программы
new[]создание массива в динамической памяти
delete[]освобождение динамического массива
утечка памятипамять занята, но путь к освобождению потерян
владелецчасть программы, отвечающая за освобождение ресурса

Связанные темы

  • Указатели — адрес первого элемента.
  • Массивы — индексы и границы.
  • Векторы — более безопасный контейнер изменяемого размера.

Источники