- 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.
- ¿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.
- 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_ptrmediantelock()para acceder al recurso.
- 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
- Resumen
int* aes 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_ptrpara propiedad exclusiva,std::shared_ptrpara propiedad compartida ystd::weak_ptrpara observar sin poseer.