Menu
Coddy logo textTech

Паттерн «Деструктор»

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

Каждый объект, созданный с помощью malloc, в конечном итоге должен быть freed. Подобно тому как мы написали create_ function для обработки allocation, мы пишем free_ function для обработки очистки. Это шаблон деструктора.

Ключевая идея заключается в том, что освобождение памяти должно выполняться в обратном порядке выделения. Если ваш constructor сначала выделил внутренние members, а затем саму структуру, ваш destructor должен сначала освободить members структуры, а затем саму структуру:

typedef struct {
    char *name;
    int age;
} Person;

void free_person(Person *p) {
    if (p == NULL) return;  // Проверка безопасности
    free(p->name);          // Сначала освободить внутренний член
    free(p);                // Затем освободить саму структуру
}

Проверка NULL в начале предотвращает сбои, если кто-то случайно передаст недопустимый указатель. После освобождения внутренней строки name мы освобождаем саму структуру. Если бы мы сначала освободили p, мы потеряли бы доступ к p->name и вызвали утечку памяти.

Использовать destructor просто:

Person *alice = create_person("Alice", 30);
// ... используйте alice ...
free_person(alice);  // Очистите, когда закончите

Этот шаблон гарантирует, что вся память будет надлежащим образом освобождена. Без него каждый создаваемый вами объект приводил бы к утечке памяти, пока в вашей программе не закончилась бы память.

challenge icon

Задание

Легко

Создадим модуль Movie, демонстрирующий полный жизненный цикл объекта: как создание, так и уничтожение. Ты попрактикуешься в написании функции-деструктора, которая правильно освобождает всю выделенную память в нужном порядке.

Тебе нужно создать три файла:

  • movie.h: Declare структуру Movie с двумя members: char *title (строка, выделенная dynamically) и int year. Declare как constructor create_movie, принимающий название и год, так и destructor free_movie, принимающий указатель Movie. Используй include guards с символом MOVIE_H.
  • movie.c: Implement обе function. Constructor должен выделить memory для структуры и её строки title (не забудь о null-терминаторе). Destructor должен освободить memory в обратном порядке allocation: first внутреннюю строку title, затем саму структуру. Для безопасности добавь проверку NULL в начале destructor.
  • main.c: Создай фильм, выведи его information, затем правильно освободи memory.

Ты получишь два входных значения: название фильма (строка) и год выпуска (целое число).

В основном файле используй create_movie, чтобы создать новый фильм, выведи его information, затем вызови free_movie, чтобы освободить всю memory. После освобождения выведи сообщение-подтверждение.

Выведи результат в следующем формате:

Movie: {title} ({year})
Memory freed

Например, для входных данных Inception и 2010 результатом будет:

Movie: Inception (2010)
Memory freed

Помни: ключ к правильному destructor — освобождение в обратном порядке. То, что constructor выделяет first, освобождается last, а то, что он выделяет last, освобождается first.

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

#include <stdio.h>
#include <stdlib.h>
#include "movie.h"

int main() {
    char title[100];
    int year;
    
    // Прочитать ввод
    scanf("%[^\n]", title);
    scanf("%d", &year);
    
    // TODO: Создать фильм с помощью create_movie
    
    // TODO: Вывести информацию о фильме в формате:
    // Фильм: {title} ({year})
    
    // TODO: Освободить фильм с помощью free_movie
    
    // TODO: Вывести "Memory freed"
    
    return 0;
}
quiz iconПроверьте себя

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

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

Потренируйтесь самостоятельно: Онлайн-компилятор C