Динамическая память (dynamic memory) — область памяти, где объекты создаются выражением new и живут, пока их явно не удалят через delete. Время жизни такого объекта не привязано ни к блоку, ни ко всей программе — им управляет программист.

Зачем нужно

Кроме динамической, в C++ есть глобальная (статическая) и автоматическая (стековая) области, а также потоковая, которую в курсе не разбирают. У глобальной и стековой есть ограничения:

  • фиксированное время жизни: глобальные переменные живут до конца программы, локальные — до конца текущего блока (см. Область действия);
  • размер: как правило, эти области ограничены несколькими мегабайтами, а реальные программы часто требуют гораздо больше.

Динамическая память снимает оба ограничения. Цена — освобождать её нужно самостоятельно.

Как работает

new

new T, new T(...), new T[...] создают в динамической области объект типа T и возвращают указатель на него. Имени у объекта нет — обращаются к нему только через указатель:

int* pa = new int;      // без инициализации
int* pb = new int(11);  // инициализация числом 11

Форма с квадратными скобками создаёт массив — см. Динамический массив.

Объект живёт с момента new независимо от блоков, поэтому его можно создать внутри блока и пользоваться им снаружи:

int* p = nullptr;
{
  p = new int(13);
}
std::cout << *p;  // Ok

delete

delete <указатель> удаляет объект и возвращает память системе:

int* p = new int;
// ...
delete p;
  • удалять можно только память, выделенную через new; иначе delete — UB;
  • delete нулевого указателя — корректная операция.

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

Утечка памяти (memory leak) — неконтролируемый рост лишней памяти: объект больше не нужен, а удалить его нельзя, потому что указатель на него потерян или о нём забыли.

int* p = new int;
p = nullptr;  // потеряли указатель — утечка
new float;    // выделили память, указатель не сохранили
p = new int;  // забыли удалить после использования — утечка

Две классические ошибки

ОшибкаНазваниеСредство
обратились к объекту после deleteuse after freeне обращаться после delete
не вызвали deletememory leakownership и RAII

Первая порождает висячий указатель. Владение (ownership) и RAII (resource acquisition is initialization) на лекции L03 только названы.

Кто освобождает

Каждый объект из new удаляется ровно один раз: ноль раз — утечка, два — двойное удаление. Правило из лекции:

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

Объект, созданный без new, удалять через delete нельзя — он уничтожится сам на выходе из блока.

malloc и operator new

В C память выделяли функцией malloc. В отличие от new, она возвращает void*, требует число байт и не инициализирует память:

int* p = static_cast<int*>(std::malloc(sizeof(int)));
*p = 0;
std::free(p);

В C++ аналог malloc/free — функции operator new и operator delete. Используются они редко, основной способ — выражения new/delete, которые внутри себя эти функции и вызывают.

Тонкости

Не из лекции

  • «Куча» (heap) — распространённое неформальное название динамической области; в лонгриде его нет.
  • Пары не смешиваются: malloc — с free, new — с delete, new[] — с delete[]. Заголовок для malloc/free — <cstdlib>.
  • Утечки ловит санитайзер: g++ -g -fsanitize=address для кода выше печатает при выходе ERROR: LeakSanitizer: detected memory leaks (GCC 16.2). См. Компиляция и сборка.

Частые ошибки

  • Потерять единственный указатель на объект — переприсвоить его или выйти из блока, где он объявлен.
  • Удалить объект дважды: и в вызывающей, и в вызываемой функции.
  • Вызвать delete для адреса обычной переменной.
  • Читать память, полученную new int или malloc, до первой записи: она не инициализирована.

Углубление — L04

Форма new T[n] создаёт в динамической памяти массив из n элементов и возвращает указатель на нулевой. В отличие от обычного массива, n не обязан быть константой времени компиляции. Память из new[] освобождается только через delete[]:

int* array = new int[10];
// ...
delete[] array;

Подробно, вместе с многомерными динамическими массивами, — в Динамический массив.