Mergulho Profundo em Destrutores
Parte da seção Programação Orientada a Objetos do Journey de C++ da Coddy — lição 24 de 104.
Um destrutor é uma função membro especial que é executada automaticamente quando um objeto é destruído. Seu trabalho principal é liberar recursos que o objeto adquiriu durante seu tempo de vida, como memória alocada dinamicamente, manipuladores de arquivos ou conexões de rede.
O destrutor tem o mesmo nome que a classe, prefixado com um til ~. Ele não recebe parâmetros e não possui tipo de retorno:
class FileHandler {
std::string filename;
int* buffer;
public:
FileHandler(std::string name, size_t size)
: filename(name), buffer(new int[size]) {
std::cout << "Opening " << filename << "\n";
}
~FileHandler() {
delete[] buffer;
std::cout << "Closing " << filename << "\n";
}
};Destrutores são chamados automaticamente nestas situações:
- Objetos de pilha saem de escopo
deleteé chamado em um objeto alocado no heap- O tempo de vida de um objeto temporário termina
void example() {
FileHandler f1("data.txt", 100); // Construtor chamado
FileHandler* f2 = new FileHandler("log.txt", 50);
delete f2; // Destrutor chamado para f2
} // Destrutor chamado para f1 (sai do escopo)Ao contrário dos construtores, uma classe pode ter apenas um destrutor. Você não pode sobrecarregá-lo.
Se você não definir um, o compilador gera um destrutor padrão que não faz nada de especial - ele simplesmente destrói cada membro. Para classes que gerenciam recursos, você deve escrever o seu próprio para evitar vazamentos de memória.
Desafio
FácilVamos construir um gerenciador de sessões que rastreia sessões de usuários ativos e demonstra como os destrutores limpam automaticamente os recursos quando os objetos são destruídos — seja quando saem de escopo ou quando são explicitamente deletados.
Você criará dois arquivos para organizar seu código:
Session.h: Defina uma classeSessionque representa uma sessão de usuário ativa com dados alocados dinamicamente. Sua classe deve ter:- Membros privados: um
username(string), umsessionId(int) e um ponteiro para um array de inteiros chamadoactivityLogque rastreia as ações do usuário, junto com umlogSizepara o tamanho do array - Um construtor que recebe um nome de usuário, ID da sessão e tamanho do log. Ele deve alocar o array do log de atividades no heap, inicializar todos os elementos com 0 e imprimir
"Session <sessionId> started for <username>" - Um destrutor que libera a memória alocada e imprime
"Session <sessionId> ended for <username>" - Um método
logActivity(int activityCode)que armazena o código da atividade no próximo slot disponível (rastreie a posição atual internamente) - Um método
getActivityCount()que retorna quantas atividades foram registradas - Um método
getUsername()que retorna o nome de usuário
- Membros privados: um
main.cpp: Demonstre o comportamento do destrutor em diferentes cenários. Leia um nome de usuário e o tamanho do log da entrada (cada um em uma linha separada) e, em seguida:- Crie um bloco de escopo usando chaves
{ }e, dentro dele, crie umaSessionalocada na pilha (stack) com o nome de usuário de entrada, ID de sessão101e o tamanho do log de entrada. Registre duas atividades com os códigos1e2, depois imprima"Stack session activities: <count>". Quando o bloco terminar, o destrutor deve ser executado automaticamente. - Após o bloco, imprima
"Stack session destroyed" - Crie uma
Sessionalocada no heap usandonewcom o nome de usuário"Guest", ID de sessão202e tamanho de log3. Registre uma atividade com o código5, imprima"Heap session activities: <count>"e, em seguida, use explicitamentedeletenela. - Após a exclusão, imprima
"Heap session destroyed"
- Crie um bloco de escopo usando chaves
Este desafio mostra as duas principais maneiras pelas quais os destrutores são chamados: automaticamente quando objetos da pilha saem de escopo e manualmente quando você deleta objetos do heap. Ambos os caminhos devem liberar adequadamente o log de atividades alocado dinamicamente para evitar vazamentos de memória.
Inclua seu arquivo de cabeçalho no main.cpp usando #include "Session.h".
Folha de consulta
Um destrutor é uma função membro especial que é executada automaticamente quando um objeto é destruído. Ele libera recursos como memória alocada dinamicamente, manipuladores de arquivos ou conexões de rede.
O destrutor tem o mesmo nome da classe, prefixado com um til ~. Ele não recebe parâmetros e não possui tipo de retorno:
class FileHandler {
std::string filename;
int* buffer;
public:
FileHandler(std::string name, size_t size)
: filename(name), buffer(new int[size]) {
std::cout << "Opening " << filename << "\n";
}
~FileHandler() {
delete[] buffer;
std::cout << "Closing " << filename << "\n";
}
};Os destrutores são chamados automaticamente quando:
- Objetos de pilha saem de escopo
deleteé chamado em um objeto alocado no heap- O tempo de vida de um objeto temporário termina
void example() {
FileHandler f1("data.txt", 100); // Construtor chamado
FileHandler* f2 = new FileHandler("log.txt", 50);
delete f2; // Destrutor chamado para f2
} // Destrutor chamado para f1 (sai de escopo)Uma classe pode ter apenas um destrutor (sem sobrecarga). Se você não definir um, o compilador gera um destrutor padrão. Para classes que gerenciam recursos, você deve escrever o seu próprio para evitar vazamentos de memória.
Experimente você mesmo
#include <iostream>
#include <string>
#include "Session.h"
using namespace std;
int main() {
// Ler entrada
string username;
int logSize;
getline(cin, username);
cin >> logSize;
// TODO: Criar um bloco de escopo com chaves { }
// Dentro do bloco:
// - Criar uma Session alocada na stack com o username de entrada, ID de sessão 101 e o tamanho de log de entrada
// - Registrar duas atividades com os códigos 1 e 2
// - Imprimir "Stack session activities: <count>"
// Quando o bloco termina, o destrutor é executado automaticamente
// TODO: Após o bloco, imprimir "Stack session destroyed"
// TODO: Criar uma Session alocada na heap usando new
// - Username: "Guest", ID de sessão: 202, tamanho de log: 3
// - Registrar uma atividade com o código 5
// - Imprimir "Heap session activities: <count>"
// - Deletar a sessão
// TODO: Após a exclusão, imprimir "Heap session destroyed"
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 de OOP
Arquivos ExternosBuild e Compilação em C++Arquivos Header e SourceNamespaces e EscopoIntrodução a OOP em C++Classes vs ObjetosO Ponteiro 'this'Métodos (Funções Membro)Atributos (Membros de Dados)Básico de Ctors e DtorsRecapitulação - Calculadora Simples4Propriedades de Classe
Membros de Instância vs EstáticosGetters e SettersFunções de Membro ConstPalavra-chave MutableMétodos e Variáveis EstáticosFunções e Classes FriendRecapitulação - Gerenciador de Conta Bancária7Herança
Herança BásicaNíveis de Acesso na HerançaOrdem de Chamada de Ctor e DtorSobrescrita de MétodosFunções Virtuais e VTableHerança MúltiplaHerança VirtualRecapitulação - Hierarquia de Funcionários2Gerenciamento de Memória
Memória Stack vs HeapPonteiros e ReferênciasMemória Dinâmica (new/delete)Smart Pointers em C++RAII em C++Recapitulação - Gerenciador de Array Dinâmico5Encapsulamento
Especificadores de Acesso em C++Especificadores de Acesso em DetalhesOcultação de InformaçãoStruct vs ClassClasses Aninhadas e InternasRecapitulação - Sistema de Registros de Alunos8Polimorfismo
Polimorfismo de Compilação vs Tempo de ExecuçãoSobrecarga de FunçõesFunções Virtuais RevisitadasFunções Virtuais PurasClasses AbstratasDesign de Interfaces em C++Dynamic Casting e RTTIRecapitulação - Calculadora de Formas3Construtores e Destrutores
Construtor PadrãoConstrutor ParametrizadoConstrutor de CópiaConstrutor de MovimentaçãoListas de Inicialização do ConstrutorConstrutores DelegadosMergulho Profundo em DestrutoresRegra dos Três / Cinco / ZeroRecapitulação - Classe String6Sobrecarga de Operadores
Introdução à Sobrecarga de OperadoresSobrecarga de Operadores AritméticosSobrecarga de Operadores de ComparaçãoOperadores de StreamSobrecarga do Operador de AtribuiçãoSobrecarga dos Operadores [] e ()Operadores de Conversão de TipoRecapitulação - Classe Matrix9Templates
Templates de FunçãoTemplates de ClasseEspecialização de TemplatesTemplates VariádicosFundamentos de SFINAE e Type TraitsRecapitulação - Container Genérico