Menu
Coddy logo textTech

Punteros inteligentes en C++

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

Los punteros inteligentes (smart pointers) son clases envolventes que gestionan automáticamente la memoria del montón (heap) por ti. Eliminan la necesidad de realizar llamadas manuales a delete al liberar la memoria cuando el puntero sale de su ámbito.

Incluya el encabezado <memory> para usar punteros inteligentes.

unique_ptr - propiedad exclusiva. Solo un puntero puede ser el propietario del recurso a la vez.

#include <memory>

std::unique_ptr<Player> player = std::make_unique<Player>("Hero");
player->attack();  // Usar como un puntero regular

// No se puede copiar, pero se puede transferir la propiedad
std::unique_ptr<Player> player2 = std::move(player);
// player ahora es nullptr

shared_ptr - propiedad compartida. Múltiples punteros pueden poseer el mismo recurso. La memoria se libera cuando el último propietario es destruido.

std::shared_ptr<Player> p1 = std::make_shared<Player>("Hero");
std::shared_ptr<Player> p2 = p1;  // Ambos son dueños del recurso

std::cout << p1.use_count();  // Imprime 2

weak_ptr - observador sin propiedad de un shared_ptr. Útil para romper referencias circulares.

std::shared_ptr<Player> shared = std::make_shared<Player>("Hero");
std::weak_ptr<Player> weak = shared;

if (auto locked = weak.lock()) {  // Convertir a shared_ptr
    locked->attack();
}

Usa unique_ptr por defecto para propiedad única. Usa shared_ptr cuando varios objetos necesiten compartir un recurso. Usa weak_ptr para observar sin extender el tiempo de vida.

Prefiere make_unique y make_shared en lugar de new directamente.

challenge icon

Desafío

Fácil

Vamos a construir un sistema para compartir documentos que demuestre los diferentes modelos de propiedad de los punteros inteligentes (smart pointers). Verás cómo unique_ptr impone la propiedad exclusiva, cómo shared_ptr permite múltiples propietarios y cómo weak_ptr puede observar sin afectar el tiempo de vida.

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

  • Document.h: Define una clase Document que represente un documento compartible. Debe tener:
    • Un atributo privado title (string)
    • Un constructor que reciba un título e imprima "Document created: <title>"
    • Un destructor que imprima "Document deleted: <title>"
    • Un método getTitle() que devuelva el título
  • main.cpp: Demuestra los tres tipos de punteros inteligentes leyendo el título de un documento desde la entrada, y luego:
    • Crea un unique_ptr a un Document con el título ingresado
    • Imprime "Unique owner: <title>"
    • Transfiere la propiedad a otro unique_ptr usando std::move
    • Imprime "Ownership transferred"
    • Crea un shared_ptr a un nuevo Document con el título "SharedDoc"
    • Crea un segundo shared_ptr que apunte al mismo documento
    • Imprime "Shared owners: <count>" usando use_count()
    • Crea un weak_ptr a partir de uno de los punteros compartidos
    • Usa lock() para acceder al documento a través del puntero débil e imprime "Weak access: <title>"

Recuerda incluir <memory> para los punteros inteligentes. Usa std::make_unique y std::make_shared para crear tus punteros inteligentes. Los mensajes del destructor te ayudarán a ver cuándo se limpia automáticamente cada documento al final del programa.

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

Hoja de referencia

Los punteros inteligentes son clases envolventes que gestionan automáticamente la memoria del montículo (heap). Incluye el encabezado <memory> para usarlos.

unique_ptr

Propiedad exclusiva - solo un puntero puede poseer el recurso a la vez:

std::unique_ptr<Player> player = std::make_unique<Player>("Hero");
player->attack();  // Úsalo como un puntero normal

// Transfiere la propiedad con std::move
std::unique_ptr<Player> player2 = std::move(player);
// player ahora es nullptr

shared_ptr

Propiedad compartida - múltiples punteros pueden poseer el mismo recurso. La memoria se libera cuando el último propietario es destruido:

std::shared_ptr<Player> p1 = std::make_shared<Player>("Hero");
std::shared_ptr<Player> p2 = p1;  // Ambos poseen el recurso

std::cout << p1.use_count();  // Imprime 2

weak_ptr

Observador sin propiedad de un shared_ptr. Útil para romper referencias circulares:

std::shared_ptr<Player> shared = std::make_shared<Player>("Hero");
std::weak_ptr<Player> weak = shared;

if (auto locked = weak.lock()) {  // Convertir a shared_ptr
    locked->attack();
}

Mejores prácticas: Usa unique_ptr por defecto para propiedad única. Usa shared_ptr cuando múltiples objetos necesiten compartir un recurso. Usa weak_ptr para observar sin extender el tiempo de vida. Prefiere make_unique y make_shared sobre el uso directo de new.

Pruébalo tú mismo

#include <iostream>
#include <memory>
#include <string>
#include "Document.h"

using namespace std;

int main() {
    string inputTitle;
    cin >> inputTitle;

    // TODO: Crear un unique_ptr a un Document con inputTitle
    // usando std::make_unique

    // TODO: Imprimir "Unique owner: <title>"

    // TODO: Transferir la propiedad a otro unique_ptr usando std::move

    // TODO: Imprimir "Ownership transferred"

    // TODO: Crear un shared_ptr a un nuevo Document con el título "SharedDoc"
    // usando std::make_shared

    // TODO: Crear un segundo shared_ptr que apunte al mismo documento

    // TODO: Imprimir "Shared owners: <count>" usando use_count()

    // TODO: Crear un weak_ptr a partir de uno de los punteros compartidos

    // TODO: Usar lock() para acceder al documento a través de weak_ptr
    // y imprimir "Weak access: <title>"

    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