Menu
Coddy logo textTech

Análisis profundo del destructor

Parte de la sección Programación Orientada a Objetos del Journey de C++ de Coddy. Lección 24 de 104.

Un destructor es una función miembro especial que se ejecuta automáticamente cuando se destruye un objeto. Su función principal es liberar los recursos que el objeto adquirió durante su ciclo de vida, como memoria asignada dinámicamente, identificadores de archivos o conexiones de red.

El destructor tiene el mismo nombre que la clase, precedido por una tilde ~. No acepta parámetros y no tiene 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";
    }
};

Los destructors se llaman automáticamente en estas situaciones:

  • Los objetos de la pila salen del ámbito
  • Se llama a delete en un objeto asignado en el montón
  • La vida útil de un objeto temporal termina
void example() {
    FileHandler f1("data.txt", 100);    // Constructor llamado
    
    FileHandler* f2 = new FileHandler("log.txt", 50);
    delete f2;                           // Destructor llamado para f2
    
}   // Destructor llamado para f1 (sale del ámbito)

A diferencia de los constructores, una clase solo puede tener un destructor. No puedes sobrecargarlo.

Si no defines uno, el compilador genera un destructor predeterminado que no hace nada especial: simplemente destruye cada miembro. Para las clases que gestionan recursos, debes escribir el tuyo propio para evitar fugas de memoria.

challenge icon

Desafío

Fácil

Construyamos un administrador de sesiones que realice un seguimiento de las sesiones de usuario activas y demuestre cómo los destructores limpian automáticamente los recursos cuando se destruyen los objetos, ya sea cuando salen de ámbito o cuando se eliminan explícitamente.

Crearás dos archivos para organizar tu código:

  • Session.h: Define una clase Session que represente una sesión de usuario activa con datos asignados dinámicamente. Tu clase debe tener:
    • Miembros privados: un username (cadena), un sessionId (entero) y un puntero a un arreglo de enteros llamado activityLog que registre las acciones del usuario, junto con un logSize para el tamaño del arreglo
    • Un constructor que reciba un nombre de usuario, un ID de sesión y un tamaño de registro. Debe asignar el arreglo de registro de actividades en el montón, inicializar todos los elementos en 0 e imprimir "Session <sessionId> started for <username>"
    • Un destructor que libere la memoria asignada e imprima "Session <sessionId> ended for <username>"
    • Un método logActivity(int activityCode) que almacene el código de actividad en la siguiente posición disponible (realiza un seguimiento interno de la posición actual)
    • Un método getActivityCount() que devuelva cuántas actividades se han registrado
    • Un método getUsername() que devuelva el nombre de usuario
  • main.cpp: Demuestra el comportamiento de los destructores en diferentes situaciones. Lee un nombre de usuario y el tamaño del registro desde la entrada (cada uno en una línea separada) y, después:
    • Crea un bloque de ámbito usando llaves { } y dentro de él crea una Session asignada en la pila con el nombre de usuario de entrada, el ID de sesión 101 y el tamaño del registro de entrada. Registra dos actividades con los códigos 1 y 2 y, después, imprime "Stack session activities: <count>". Cuando termina el bloque, el destructor debe ejecutarse automáticamente.
    • Después del bloque, imprime "Stack session destroyed"
    • Crea una Session asignada en el montón usando new, con el nombre de usuario "Guest", el ID de sesión 202 y el tamaño de registro 3. Registra una actividad con el código 5, imprime "Heap session activities: <count>" y, después, elimínala explícitamente con delete.
    • Después de la eliminación, imprime "Heap session destroyed"

Este desafío muestra las dos formas principales en que se invocan los destructores: automáticamente, cuando los objetos de la pila salen del ámbito, y manualmente, cuando eliminas objetos del montón. Ambas rutas deben liberar correctamente el registro de actividades asignado dinámicamente para evitar fugas de memoria.

Incluye tu archivo de encabezado en main.cpp usando #include "Session.h".

Pruébalo tú mismo

#include <iostream>
#include <string>
#include "Session.h"

using namespace std;

int main() {
    // Leer entrada
    string username;
    int logSize;
    getline(cin, username);
    cin >> logSize;
    
    // TODO: Crea un bloque de alcance con llaves { }
    // Dentro del bloque:
    //   - Crea un Session asignado en la pila con el username de entrada, session ID 101 y el log size de entrada
    //   - Registra dos actividades con códigos 1 y 2
    //   - Print "Stack session activities: <count>"
    // Cuando el bloque termina, el destructor se ejecuta automáticamente
    
    // TODO: After the block, print "Stack session destroyed"
    
    // TODO: Crea un Session asignado en el heap usando new
    //   - Username: "Guest", session ID: 202, log size: 3
    //   - Registra una actividad con código 5
    //   - Print "Heap session activities: <count>"
    //   - Elimina la sesión
    
    // TODO: After deletion, print "Heap session destroyed"
    
    return 0;
}
quiz iconPonte a prueba

Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.

Todas las lecciones de Programación Orientada a Objetos

Practica por tu cuenta: Compilador de C++ online