Punteros inteligentes frente a punteros crudos en C++

  1. Punteros crudos y su riesgo

Un puntero crudo como int* ptr es una variable que almacena una dirección de memoria. Aunque es potente, requiere gestión manual: debes recordar liberar la memoria con delete, evitar liberarla dos veces y no acceder a ella tras liberarla. Estos errores provocan fugas de memoria o fallos de programa.

  1. ¿Qué es un puntero inteligente?

Un puntero inteligente (std::unique_ptr, std::shared_ptr, std::weak_ptr) es un objeto de clase que envuelve un puntero crudo y aplica el principio RAII (Resource Acquisition Is Initialization). Al construirse, adquiere el recurso (memoria dinámica) y al destruirse (cuando sale del ámbito), libera automáticamente la memoria mediante su destructor. Es como tener un "mayordomo" que se encarga de la limpeiza.

  1. Los tres tipos principales

a) std::unique_ptr (propietario exclusivo)

  • Solo una instancia puede poseer el recurso en un momento dado.
  • No se puede copiar, solo mover (std::move).
  • Sin sobrecarga adicional (casi nula).

b) std::shared_ptr (propietario compartido)

  • Mantiene un contador de referencias.
  • Cada copia incrementa el contador; cada destrucción lo decrementa.
  • El recurso se libera cuando el contador llega a cero.
  • Ideal para datos compartidos entre varios objetos.

c) std::weak_ptr (observador no propietario)

  • No incremenat el contador de referencias de shared_ptr.
  • Se usa para evitar ciclos que impedirían la liberación de memoria.
  • Debe convertirse a shared_ptr mediante lock() para acceder al recurso.
  1. Comparación de código: manual vs automático

Con puntero crudo (riesgoso):

void funcionArriesgada() {
    int* ptr = new int(42);
    if (condicionError) {
        // Si ocurre un error y salimos antes de delete, hay fuga de memoria
        return;
    }
    delete ptr;
}

Con puntero inteligente (seguro):

#include <memory>

void funcionSegura() {
    auto ptr = std::make_unique<int>(42);  // unique_ptr
    if (condicionError) {
        // Incluso si hay un return, el destructor de ptr libera la memoria
        return;
    }
    // No es necesario llamar a delete
}

Ejemplo con shared_ptr:

#include <memory>

void ejemploCompartido() {
    std::shared_ptr<int> sp1 = std::make_shared<int>(100);
    {
        std::shared_ptr<int> sp2 = sp1;  // contador = 2
        // usar sp2...
    } // sp2 se destruye, contador = 1
    // sp1 sigue vivo
} // sp1 se destruye, contador = 0, memoria liberada
  1. Resumen

  • int* a es un puntero crudo que exige gestión manual y es propenso a errores.
  • Los punteros inteligentes (RAII) automatizan la liberaicón de memoria, eliminando fugas y dobles liberaciones.
  • Usa std::unique_ptr para propiedad exclusiva, std::shared_ptr para propiedad compartida y std::weak_ptr para observar sin poseer.

Etiquetas: RAII std::unique_ptr std::shared_ptr std::weak_ptr puntero crudo

Publicado el 6-5 19:45