Menu
Coddy logo textTech

Aprofundamento 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. Sua principal função é liberar os recursos que o objeto adquiriu durante seu ciclo de vida, como memória alocada dinamicamente, identificadores de arquivo ou conexões de rede.

O destrutor tem o mesmo nome da classe, precedido por um til ~. Ele não recebe parâmetros e não tem 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";
    }
};

Destructors são chamados automaticamente nestas situações:

  • Objetos na pilha saem do escopo
  • delete é chamado em um objeto alocado na 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. Não é possível 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.

challenge icon

Desafio

Fácil

Vamos criar um gerenciador de sessões que rastreia sessões de usuários ativas e demonstra como os destruidores limpam automaticamente os recursos quando os objetos são destruídos, seja quando saem do escopo ou quando são excluídos explicitamente.

Você criará dois arquivos para organizar seu código:

  • Session.h: defina uma classe Session que represente uma sessão de usuário ativa com dados alocados dinamicamente. Sua classe deve ter:
    • Membros privados: um username (string), um sessionId (int) e um ponteiro para um array de inteiros chamado activityLog que rastreia as ações do usuário, além de um logSize para o tamanho do array
    • Um construtor que receba um username, um ID de sessão e o tamanho do log. Ele deve alocar o array de log de atividades no heap, inicializar todos os elementos com 0 e imprimir "Session <sessionId> started for <username>"
    • Um destruidor que libere a memória alocada e imprima "Session <sessionId> ended for <username>"
    • Um método logActivity(int activityCode) que armazene o código da atividade no próximo espaço disponível (rastreie internamente a posição atual)
    • Um método getActivityCount() que retorne quantas atividades foram registradas
    • Um método getUsername() que retorne o username
  • main.cpp: demonstre o comportamento do destruidor em diferentes cenários. Leia um username 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 uma Session alocada na stack com o username informado, o ID de sessão 101 e o tamanho de log informado. Registre duas atividades com os códigos 1 e 2 e, em seguida, imprima "Stack session activities: <count>". Quando o bloco terminar, o destruidor deverá ser executado automaticamente.
    • Após o bloco, imprima "Stack session destroyed"
    • Crie uma Session alocada no heap usando new, com o username "Guest", o ID de sessão 202 e o tamanho de log 3. Registre uma atividade com o código 5, imprima "Heap session activities: <count>" e, em seguida, use explicitamente delete nela.
    • Após a exclusão, imprima "Heap session destroyed"

Este desafio mostra as duas principais maneiras pelas quais os destruidores são chamados: automaticamente, quando os objetos na stack saem do escopo, e manualmente, quando você exclui objetos no heap. Ambos os caminhos devem liberar corretamente o log de atividades alocado dinamicamente para evitar vazamentos de memória.

Inclua seu arquivo de cabeçalho em main.cpp usando #include "Session.h".

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: Crie um bloco de escopo com chaves { }
    // Dentro do bloco:
    //   - Crie um Session alocado na stack com o username de entrada, session ID 101 e o log size de entrada
    //   - Registre duas atividades com códigos 1 e 2
    //   - Print "Stack session activities: <count>"
    // Quando o bloco termina, o destrutor é executado automaticamente
    
    // TODO: After the block, print "Stack session destroyed"
    
    // TODO: Crie um Session alocado na heap usando new
    //   - Username: "Guest", session ID: 202, log size: 3
    //   - Registre uma atividade com código 5
    //   - Print "Heap session activities: <count>"
    //   - Delete a sessão
    
    // TODO: After deletion, print "Heap session destroyed"
    
    return 0;
}
quiz iconTeste seus conhecimentos

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

Pratique por conta própria: Compilador de C++ online