Ver Mensaje Individual
  #4 (permalink)  
Antiguo 26/09/2016, 06:46
eferion
 
Fecha de Ingreso: octubre-2014
Ubicación: Madrid
Mensajes: 1.212
Antigüedad: 10 años, 1 mes
Puntos: 204
Respuesta: Vector de punteros cuando muda a otro lado

Cita:
Iniciado por dmorill Ver Mensaje
No conocía los shared_ptr ni los unique_ptr.
Son lo que se conoce como punteros inteligentes. La gracia de estas clases es que se encargan de la gestión de un puntero, destruyéndolo cuando el mismo ya no es necesario.

unique_ptr es una clase que se encarga de la gestión de un puntero que no va a ser compartido. Cuando la ejecución abandona el ámbito de la variable el puntero se destruye automáticamente:

Código C++:
Ver original
  1. struct Test
  2. {
  3.   ~Test()
  4.   { std::cout << "Test::~Test()\n"; }
  5. }
  6.  
  7. void func()
  8. {
  9.   auto ptr = std::make_unique<Test>();
  10.   std::cout << "Despues de esto se llama al destructor\n";
  11. }
  12.  
  13. int main()
  14. {
  15.   func();
  16. }

Por supuesto un unique_ptr puede sacarse de una función (e incluso almacenarse en un contenedor). La única limitación (y es su razón de ser) es que el puntero no está compartido por otros punteros inteligentes:

Código C++:
Ver original
  1. std::unique_ptr<Test> func()
  2. {
  3.   return std::make_unique<Test>();
  4.   std::cout << "Aun no se llama al destructor\n";
  5. }
  6.  
  7. int main()
  8. {
  9.   auto ptr = func();
  10.   std::cout << "El objeto se destruye a continuacion\n";
  11. }

Para mover el puntero de una variable a otra... por ejemplo un bucle intermedio que pretende localizar un elemento en cuestión, se debe usar la sintaxis move (recuerda que al ser un elemento único no se puede llamar al constructor copia ni al de asignación alegremente):

Código C++:
Ver original
  1. void Print(std::unique_ptr<int>& var)
  2. {
  3.   if( var )
  4.     std::cout << *var << '\n';
  5.   else
  6.     std::cout << "Puntero vacio\n";
  7. }
  8.  
  9. int main()
  10. {
  11.   std::unique_ptr<int> a = std::make_unique<int>(2);
  12.   std::unique_ptr<int> b;
  13.  
  14.   Print(a); Print(b);
  15.  
  16.   //b = a; -> ERROR de compilación
  17.  
  18.   b = std::move(a); // sintaxis MOVE. a y b intercambian sus estados
  19.  
  20.   Print(a); Print(b);
  21. }

Gestionar los punteros con punteros inteligentes ayuda a reducir las fugas de memoria:
Código C++:
Ver original
  1. std::unique_ptr<Test> func()
  2. {
  3.   auto obj = std::make_unique<Test>();
  4.   throw 1; // Al lanzar la excepción el objeto se destruye automáticamente
  5.   return obj;
  6. }
  7.  
  8. int main()
  9. {
  10.   try
  11.   {
  12.     func();
  13.   }
  14.  
  15.   catch(...)
  16.   { }
  17. }

shared_ptr sigue la misma filosofía (proporcionar un mecanismo de gestión de la memoria) pero permite que el puntero esté compartido por varias variables. Lo que hace shared_ptr es invocar al destructor automáticamente cuando el puntero ya no tiene referencias.

El uso de shared_ptr requiere prestar atención a las referencias circulares. Recordemos que si un shared_ptr tiene al menos una referencia el objeto no se va a destruir, luego si A apunta a B y B a A, ninguno de los dos objetos se va a destruir.

Un saludo.
__________________
La ayuda se paga con esfuerzo o con dinero. Si no estás dispuesto a esforzarte y quieres que te hagan los deberes pide presupuesto, al menos así ahorrarás tiempo.