Padrão de Destrutor
Parte da seção Programação Orientada a Objetos do Journey de C da Coddy. Lição 13 de 61.
Todo objeto criado com malloc deve ser eventualmente liberado. Assim como escrevemos uma função create_ para lidar com a alocação, escrevemos uma função free_ para lidar com a limpeza. Esse é o padrão destrutor.
A ideia fundamental é que a liberação deve ocorrer na ordem inversa da alocação. Se o seu construtor alocou primeiro os membros internos e depois a própria struct, o destrutor deve liberar primeiro os membros da struct e, em seguida, a struct:
typedef struct {
char *name;
int age;
} Person;
void free_person(Person *p) {
if (p == NULL) return; // Verificação de segurança
free(p->name); // Libera o membro interno primeiro
free(p); // Depois libera a própria struct
}
A verificação de NULL no início evita falhas caso alguém passe acidentalmente um ponteiro inválido. Depois de liberar a string interna name, liberamos a própria struct. Se liberássemos p primeiro, perderíamos o acesso a p->name e causaríamos um vazamento de memória.
Usar o destrutor é simples:
Person *alice = create_person("Alice", 30);
// ... use alice ...
free_person(alice); // Limpe quando terminar
Este padrão garante que toda a memória seja devidamente liberada. Sem ele, cada objeto que você criar vazaria memória até que seu programa ficasse sem memória.
Desafio
FácilVamos criar um módulo Movie que demonstra o ciclo de vida completo de um objeto: tanto a criação quanto a destruição. Você praticará como escrever uma função destrutora que libera corretamente toda a memória alocada, na ordem correta.
Você criará três arquivos:
movie.h: Declare uma structMoviecom dois membros:char *title(uma string alocada dinamicamente) eint year. Declare tanto um construtorcreate_movie, que recebe um título e um ano, quanto uma destrutorafree_movie, que recebe um ponteiro para Movie. Use guardas de inclusão com o símboloMOVIE_H.movie.c: Implemente ambas as funções. Seu construtor deve alocar memória para a struct e para sua string de título (não se esqueça do terminador nulo). Sua destrutora deve liberar a memória na ordem inversa da alocação: primeiro a string internatitle, depois a própria struct. Inclua uma verificação de NULL no início da sua destrutora por segurança.main.c: Crie um filme, exiba suas informações e depois libere corretamente a memória.
Você receberá duas entradas: o título do filme (uma string) e o ano de lançamento (um inteiro).
Em seu arquivo principal, use create_movie para criar um novo filme, exiba suas informações e depois chame free_movie para liberar toda a memória. Após liberar a memória, exiba uma mensagem de confirmação.
Exiba a saída neste formato:
Movie: {title} ({year})
Memory freedPor exemplo, com as entradas Inception e 2010, a saída seria:
Movie: Inception (2010)
Memory freedLembre-se: a chave para uma destrutora adequada é liberar na ordem inversa. O que quer que seu construtor aloque primeiro será liberado por último, e o que quer que ele aloque por último será liberado primeiro.
Experimente você mesmo
#include <stdio.h>
#include <stdlib.h>
#include "movie.h"
int main() {
char title[100];
int year;
// Ler entrada
scanf("%[^\n]", title);
scanf("%d", &year);
// TODO: Criar um filme usando create_movie
// TODO: Imprimir as informações do filme no formato:
// Movie: {title} ({year})
// TODO: Liberar o filme usando free_movie
// TODO: Imprimir "Memory freed"
return 0;
}
Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.
Todas as lições de Programação Orientada a Objetos
1Fundamentos da Programação Modular
Arquivos de CabeçalhoInclude GuardsArquivos-FonteFunções EstáticasRecapitulação: Calculadora Modular4Encapsulamento
Conceito de Ponteiros OpacosDefinindo Structs OpacasGetters e SettersValidação em SettersRecapitulação: Caixa Secreta2Objetos e Métodos
Structs como ObjetosO Ponteiro 'Self'Const CorrectnessPonteiro vs ValorMétodos AuxiliaresRecapitulação: Point Manager5Projeto: Conta Bancária Simples
Configuração do ProjetoImplementação da Conta3Ciclo de Vida de Objetos
Padrão de ConstrutorPadrão de DestrutorInicialização na StackCópia ProfundaRecapitulação: String Wrapper6Herança via Composição
Incorporação de StructsA Regra do Primeiro MembroAcessando Membros PaiUpcastingRecapitulação: Hierarquia de Formas9Projeto: Desenhador de Formas
Visão Geral do ProjetoImplementação do CírculoImplementação do RetânguloUso PolimórficoContainer de FormasPratique por conta própria: Compilador de C online