Lección 7 · 7 de 20
unique_ptr y shared_ptr · C++
Use los punteros inteligentes unique_ptr y shared_ptr de C++ para que la memoria se libere sola: canciones con uno o con varios dueños.

Un puntero inteligente es un objeto que guarda un puntero y aplica RAII: cuando deja de existir, libera la memoria. Ya no hace falta new ni delete: std::make_unique<Song>("Demo take") crea la canción y devuelve un `std::unique_ptr` que la posee. El destructor de Song escribe un mensaje para ver cuándo se libera cada una.
unique_ptr tiene un solo dueño, así que no se puede copiar, pero sí mover: std::move(demo) pasa la propiedad a keeper y deja demo vacío (en una condición, un puntero vacío vale false). keeper.reset() libera la canción en ese mismo momento; si no, se habría liberado al final de main. La flecha funciona como con un puntero normal: demo->title.
`std::shared_ptr` admite varios dueños y lleva la cuenta, que da use_count(). hit y las dos listas, rock y party, comparten la misma canción, así que hay 3 dueños. Al vaciar rock y hacer hit.reset() queda uno, y la canción sigue viva en party.
La canción se libera cuando desaparece su último dueño: el vector party, al terminar main. Por eso «(freed Summer Nights)» sale después de «End of main». Use unique_ptr por defecto, que no cuesta nada frente a un puntero normal, y shared_ptr solo cuando la propiedad sea compartida de verdad.
Código · main.cpp
#include <iostream>#include <memory>#include <string>#include <vector>struct Song { std::string title; explicit Song(std::string t) : title(t) {} ~Song() { std::cout << " (freed " << title << ")\n"; }};int main() { // unique_ptr: a single owner that frees the object when it goes away. std::unique_ptr<Song> demo = std::make_unique<Song>("Demo take"); std::cout << "Unique: " << demo->title << "\n"; std::unique_ptr<Song> keeper = std::move(demo); // ownership moves; it cannot be copied std::cout << "demo is " << (demo ? "full" : "empty") << " now\n"; keeper.reset(); // freed right here // shared_ptr: several owners and a count of them. auto hit = std::make_shared<Song>("Summer Nights"); std::vector<std::shared_ptr<Song>> rock, party; rock.push_back(hit); party.push_back(hit); std::cout << "Owners of " << hit->title << ": " << hit.use_count() << "\n"; rock.clear(); hit.reset(); std::cout << "Left in party: " << party[0]->title << " (owners: " << party[0].use_count() << ")\n"; std::cout << "End of main\n";} // party is destroyed: its last owner frees the songSalida · c++ -std=c++17 main.cpp -o main && ./main
Unique: Demo take demo is empty now (freed Demo take) Owners of Summer Nights: 3 Left in party: Summer Nights (owners: 1) End of main (freed Summer Nights)
Para recordar
- Cree los objetos con
std::make_uniqueystd::make_shared, no connew. unique_ptr: un solo dueño; se mueve constd::move, no se copia.shared_ptr: varios dueños; el objeto vive mientras quede alguno.reset()suelta el objeto; un puntero vacío valefalse.- Prefiera
unique_ptrsalvo que necesite compartir.
Ejercicio
Cree una tercera lista, chill, añádale hit antes de rock.clear() y escriba use_count() después de cada paso. ¿Cuándo se libera ahora la canción?