Historia del problema:
Los punteros normales (crudos) son el mecanismo tradicional en C++ para trabajar con memoria dinámica. Este es un mecanismo abstracto universal, pero, desafortunadamente, es muy propenso a errores: fugas de memoria, eliminación doble, errores de puntero colgante. Por lo tanto, desde C++11, la biblioteca estándar incluye punteros inteligentes: clases de plantilla (std::unique_ptr, std::shared_ptr, std::weak_ptr) que administran automáticamente la vida útil de un objeto.
Problema:
Al usar punteros normales, la responsabilidad de la asignación y liberación de memoria recae en el programador. Los errores en la liberación de memoria conducen a fugas (memory leaks), destrucción de datos y caídas del programa. Los casos especialmente complejos ocurren en el manejo de excepciones o al pasar punteros a otras funciones.
Solución:
Los punteros inteligentes encapsulan la memoria asignada y la liberan automáticamente cuando ya no hay propietarios. Implementan RAII. std::unique_ptr proporciona propiedad exclusiva, std::shared_ptr — propiedad compartida, std::weak_ptr — no controlante (para prevenir "ciclos de referencia").
Ejemplo de código:
#include <memory> void foo() { std::unique_ptr<int> p = std::make_unique<int>(5); // la memoria se liberará incluso en caso de excepción // ... }
Características clave:
¿Se puede usar std::unique_ptr en un arreglo creado con new[]?
No, para arreglos utiliza std::unique_ptr<T[]>: así se llamará a delete[] en lugar de delete.
std::unique_ptr<int[]> arr(new int[10]);
¿Los punteros inteligentes estándar pueden prevenir todas las posibles fugas de memoria?
No. Por ejemplo, las referencias cíclicas entre std::shared_ptr llevarán a fugas. Para romper tales ciclos se utiliza std::weak_ptr.
¿Pueden los punteros inteligentes "eliminar" el mismo objeto dos veces?
No, a menos que se rompa la lógica de propiedad (¡no uses punteros crudos!). Si copias manualmente un puntero crudo, la destrucción puede ocurrir dos veces.
Se utilizan punteros crudos, la memoria se libera manualmente, al lanzar una excepción la memoria no se libera.
Ventajas:
Desventajas:
Se utilizan std::unique_ptr y std::make_unique para crear objetos y pasarlos a funciones.
Ventajas:
Desventajas: