Menu
Coddy logo textTech

Memoria dinámica (new/delete)

Parte de la sección Programación Orientada a Objetos del Journey de C++ de Coddy — lección 14 de 104.

Ahora que entiendes los punteros y las referencias, pongámoslos a trabajar con la asignación dinámica de memoria. Los operadores new y delete te permiten crear y destruir objetos en el heap en tiempo de ejecución.

Usa new para asignar memoria y obtener un puntero a ella:

int* num = new int;        // Asignar un solo entero
*num = 42;                 // Asignar valor a través del puntero

Player* player = new Player("Hero");  // Asignar objeto

Cada new debe tener un delete correspondiente para liberar la memoria:

delete num;      // Liberar un solo objeto
delete player;   // Llama al destructor, luego libera la memoria

Para arrays, usa new[] y delete[]:

int* scores = new int[5];    // Asignar un array de 5 enteros
scores[0] = 100;

delete[] scores;             // Liberar el array - ¡nota los corchetes!

Errores comunes a evitar:

// Fuga de memoria - se olvidó de liberar (delete)
int* ptr = new int(10);
ptr = new int(20);    // ¡Se perdió el acceso a la primera asignación!

// Puntero colgante - uso después de borrar (delete)
delete ptr;
*ptr = 5;             // ¡Comportamiento indefinido!

// Uso incorrecto de delete
int* arr = new int[10];
delete arr;           // ¡Incorrecto! Debería ser delete[]

Después de eliminar, establece los punteros a nullptr para evitar su reutilización accidental. La gestión manual de la memoria es propensa a errores, razón por la cual el C++ moderno prefiere los punteros inteligentes, que exploraremos a continuación.

challenge icon

Desafío

Fácil

Vamos a construir un sistema simple de almacenamiento de mensajes que demuestre la asignación dinámica de memoria con new y delete.

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

  • MessageBox.h: Define una clase MessageBox que gestione dinámicamente un arreglo de mensajes. La clase debe tener:
    • Un puntero privado a un arreglo de cadenas (strings) asignado dinámicamente
    • Un entero privado que rastree el conteo actual de mensajes
    • Un entero privado que almacene la capacidad máxima
    • Un constructor que reciba una capacidad y asigne el arreglo usando new[]
    • Un destructor que libere adecuadamente la memoria usando delete[] e imprima "MessageBox destroyed"
    • Un método addMessage(string msg) que añada un mensaje si hay espacio, devolviendo true en caso de éxito o false si está lleno
    • Un método printAll() que imprima cada mensaje almacenado en su propia línea
  • main.cpp: Lee un valor de capacidad y un número de mensajes desde la entrada. Luego lee esa cantidad de cadenas de mensajes. Crea un MessageBox en el heap usando new, añádele todos los mensajes, llama a printAll() y luego elimina adecuadamente el MessageBox para liberar memoria.

El formato de entrada será:

  • Primera línea: la capacidad (entero)
  • Segunda línea: el número de mensajes a añadir (entero)
  • Líneas siguientes: un mensaje por línea

Recuerda: cada new necesita un delete correspondiente, y cada new[] necesita un delete[] correspondiente. Después de eliminar, es una buena práctica establecer los punteros a nullptr.

Incluye tu archivo de cabecera en main.cpp usando #include "MessageBox.h".

Hoja de referencia

Usa new para asignar memoria dinámicamente en el heap y obtener un puntero a ella:

int* num = new int;        // Allocate single integer
*num = 42;                 // Assign value through pointer

Player* player = new Player("Hero");  // Allocate object

Cada new debe tener un delete correspondiente para liberar la memoria:

delete num;      // Free single object
delete player;   // Calls destructor, then frees memory

Para arreglos, usa new[] y delete[]:

int* scores = new int[5];    // Allocate array of 5 integers
scores[0] = 100;

delete[] scores;             // Free array - note the brackets!

Errores comunes a evitar:

// Memory leak - forgot to delete
int* ptr = new int(10);
ptr = new int(20);    // Lost access to first allocation!

// Dangling pointer - using after delete
delete ptr;
*ptr = 5;             // Undefined behavior!

// Mismatched delete
int* arr = new int[10];
delete arr;           // Wrong! Should be delete[]

Después de borrar, establece los punteros a nullptr para evitar su reutilización accidental.

Pruébalo tú mismo

#include <iostream>
#include <string>
#include "MessageBox.h"
using namespace std;

int main() {
    int capacity;
    int numMessages;
    
    // Leer la capacidad y el número de mensajes
    cin >> capacity;
    cin >> numMessages;
    cin.ignore(); // Limpiar el salto de línea después del número
    
    // TODO: Crear un MessageBox en el heap usando new
    
    // TODO: Leer y añadir todos los mensajes al MessageBox
    for (int i = 0; i < numMessages; i++) {
        string message;
        getline(cin, message);
        // Añadir el mensaje al MessageBox
    }
    
    // TODO: Llamar a printAll() para mostrar todos los mensajes
    
    // TODO: Eliminar el MessageBox para liberar memoria
    // Recuerda establecer el puntero a nullptr después de eliminar
    
    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