Menu
Coddy logo textTech

Динамическая память (new/delete)

Часть раздела Объектно-ориентированное программирование путешествия по C++ на Coddy — урок 14 из 104.

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

Используйте new для выделения памяти и получения указателя на неё:

int* num = new int;        // Выделение памяти под одно целое число
*num = 42;                 // Присваивание значения через указатель

Player* player = new Player("Hero");  // Выделение памяти под объект

Каждый new должен иметь соответствующий delete для освобождения памяти:

delete num;      // Освобождение одного объекта
delete player;   // Вызывает деструктор, затем освобождает память

Для массивов используйте new[] и delete[]:

int* scores = new int[5];    // Выделение памяти под массив из 5 целых чисел
scores[0] = 100;

delete[] scores;             // Освобождение памяти массива — обратите внимание на скобки!

Распространенные ошибки, которых следует избегать:

// Утечка памяти — забыли вызвать delete
int* ptr = new int(10);
ptr = new int(20);    // Потерян доступ к первому выделению памяти!

// Висячий указатель — использование после удаления
delete ptr;
*ptr = 5;             // Неопределенное поведение!

// Несоответствующий delete
int* arr = new int[10];
delete arr;           // Ошибка! Должно быть delete[]

После удаления устанавливайте указатели в nullptr, чтобы избежать случайного повторного использования. Ручное управление памятью подвержено ошибкам, поэтому в современном C++ предпочтительнее использовать умные указатели, которые мы изучим далее.

challenge icon

Задание

Легко

Давайте создадим простую систему хранения сообщений, которая демонстрирует динамическое выделение памяти с помощью new и delete.

Вы создадите два файла для организации вашего кода:

  • MessageBox.h: Определите класс MessageBox, который динамически управляет массивом строк. Класс должен содержать:
    • Приватный указатель на динамически выделенный массив строк
    • Приватную целую переменную для отслеживания текущего количества сообщений
    • Приватную целую переменную для хранения максимальной емкости
    • Конструктор, который принимает емкость и выделяет массив с помощью new[]
    • Деструктор, который правильно освобождает память с помощью delete[] и выводит "MessageBox destroyed"
    • Метод addMessage(string msg), который добавляет сообщение, если есть место, возвращая true в случае успеха или false, если массив заполнен
    • Метод printAll(), который выводит каждое сохраненное сообщение на новой строке
  • main.cpp: Считайте значение емкости и количество сообщений из входных данных. Затем считайте соответствующее количество строк сообщений. Создайте объект MessageBox в куче с помощью new, добавьте в него все сообщения, вызовите printAll(), а затем правильно удалите MessageBox, чтобы освободить память.

Формат входных данных:

  • Первая строка: емкость (целое число)
  • Вторая строка: количество добавляемых сообщений (целое число)
  • Следующие строки: по одному сообщению на строку

Помните: каждому new должен соответствовать delete, а каждому new[]delete[]. После удаления рекомендуется устанавливать указатели в nullptr.

Включите ваш заголовочный файл в main.cpp с помощью #include "MessageBox.h".

Шпаргалка

Используйте new для динамического выделения памяти в куче и получения указателя на неё:

int* num = new int;        // Allocate single integer
*num = 42;                 // Assign value through pointer

Player* player = new Player("Hero");  // Allocate object

Для каждого new должен быть соответствующий delete, чтобы освободить память:

delete num;      // Free single object
delete player;   // Calls destructor, then frees memory

Для массивов используйте new[] и delete[]:

int* scores = new int[5];    // Allocate array of 5 integers
scores[0] = 100;

delete[] scores;             // Free array - note the brackets!

Распространенные ошибки, которых следует избегать:

// Memory leak - forgot to delete
int* ptr = new int(10);
ptr = new int(20);    // Lost access to first allocation!

// Dangling pointer - using after delete
delete ptr;
*ptr = 5;             // Undefined behavior!

// Mismatched delete
int* arr = new int[10];
delete arr;           // Wrong! Should be delete[]

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

Попробуйте сами

#include <iostream>
#include <string>
#include "MessageBox.h"
using namespace std;

int main() {
    int capacity;
    int numMessages;
    
    // Считать вместимость и количество сообщений
    cin >> capacity;
    cin >> numMessages;
    cin.ignore(); // Очистить символ новой строки после числа
    
    // TODO: Создать MessageBox в куче, используя new
    
    // TODO: Прочитать и добавить все сообщения в MessageBox
    for (int i = 0; i < numMessages; i++) {
        string message;
        getline(cin, message);
        // Добавить сообщение в MessageBox
    }
    
    // TODO: Вызвать printAll(), чтобы отобразить все сообщения
    
    // TODO: Удалить MessageBox, чтобы освободить память
    // Не забудьте установить указатель в nullptr после удаления
    
    return 0;
}
quiz iconПроверьте себя

В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.

Все уроки раздела Объектно-ориентированное программирование