Паттерн «Деструктор»
Часть раздела Объектно-ориентированное программирование путешествия по 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); // Очистите, когда закончите
Этот шаблон гарантирует, что вся память будет надлежащим образом освобождена. Без него каждый создаваемый вами объект приводил бы к утечке памяти, пока в вашей программе не закончилась бы память.
Задание
ЛегкоСоздадим модуль Movie, демонстрирующий полный жизненный цикл объекта: как создание, так и уничтожение. Ты попрактикуешься в написании функции-деструктора, которая правильно освобождает всю выделенную память в нужном порядке.
Тебе нужно создать три файла:
movie.h: Declare структуруMovieс двумя members:char *title(строка, выделенная dynamically) иint year. Declare как constructorcreate_movie, принимающий название и год, так и destructorfree_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;
}
В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Объектно-ориентированное программирование
1Основы модульного программирования
Заголовочные файлыСтражи включенияИсходные файлыСтатические функцииПовторение: Модульный калькулятор4Инкапсуляция
Концепция непрозрачных указателейОпределение непрозрачных структурГеттеры и сеттерыВалидация в сеттерахИтоги: Секретный ящик2Объекты и методы
Структуры как объектыУказатель 'Self'Константная корректностьУказатель против значенияВспомогательные методыИтоги: Point Manager5Проект: Простой банковский счет
Настройка проектаРеализация счета3Жизненный цикл объекта
Паттерн «Конструктор»Паттерн «Деструктор»Инициализация в стекеГлубокое копированиеПовторение: String Wrapper6Наследование через композицию
Встраивание структурПравило первого элементаДоступ к элементам родителяUpcastingПовторение: Иерархия фигур9Проект: Рисование фигур
Обзор проектаРеализация кругаРеализация прямоугольникаПолиморфное использованиеКонтейнер фигурПотренируйтесь самостоятельно: Онлайн-компилятор C