Ver Mensaje Individual
  #2 (permalink)  
Antiguo 26/09/2016, 01:24
eferion
 
Fecha de Ingreso: octubre-2014
Ubicación: Madrid
Mensajes: 1.212
Antigüedad: 9 años, 7 meses
Puntos: 204
Respuesta: Vector de punteros cuando muda a otro lado

Y por qué no usas shared_ptr o unique_ptr??

Si tienes claro que la vida de 's' siempre va a ser superior a los nodos del grafo puedes usar unique_ptr. Si la vida de los objetos pasa a ser más difusa entonces es más recomendable usar shared_ptr:

Ejemplo para unique_ptr:
Código C++:
Ver original
  1. vector<std::unique_ptr<SuperNode>> s(n);
  2. for( auto& node : s )
  3.   node = std::make_unique<SuperNode>();
  4.  
  5. // make_unique<> es un template que crea un unique_ptr ya inicializado
  6. // make_unique<SuperNode>()  es equivalente a
  7. // std::unique_ptr<SuperNode>(new SuperNode);
  8. // make_unique también admite parámetros:
  9. // make_unique<SuperNode>(1) es equivalente a
  10. // std::unique_ptr<SuperNode>(new SuperNode(1));

Y para que los nodos apunten al puntero:

Código C++:
Ver original
  1. class Node
  2. {
  3.   SuperNode* superNode;
  4. };
  5. node->superNode = s[0].get();

Opción con shared_ptr (1):

Código C++:
Ver original
  1. vector<std::shared_ptr<SuperNode>> s(n);
  2. for( auto& node : s )
  3.   node = std::make_shared<SuperNode>();

Y para referenciar el puntero:

Código C++:
Ver original
  1. class Node
  2. {
  3.   std::weak_ptr<SuperNode> superNode;
  4. };
  5.  
  6. node->superNode = s[0]; // La conversión a weak es implícita

¿Por qué usar weak? shared_ptr es una clase que gestiona un puntero que va a utilizarse en varias secciones del código. Lo que hace shared_ptr es mantener vivo el puntero mientras existan referencias al mismo (una referencia = una instancia de shared_ptr referenciando al puntero). Cuando ya no hay elementos shared_ptr referenciando el puntero la memoria es liberada de forma automática.

Si resulta que tienes una referencia circular (A referencia a B y B a A), entonces la memoria nunca se liberaría porque ambos punteros tendrían siempre una referencia.... en estos casos es donde entra en acción weak_ptr. weak_ptr representa una referencia débil a un puntero compartido. Es debil porque no impide que el puntero sea destruído (no cuenta como referencia). Para evitar problemas el propio weak_ptr incluye funcionalidad que indica si el puntero está vivo o no.

Un ejemplo ilustrativo:

Código C++:
Ver original
  1. void CrearShared(std::weak_ptr<int> weakPtr)
  2. {
  3.   if( std::shared_ptr<int> miShared = weakPtr.lock() )
  4.   {
  5.     std::cout << "El puntero esta referenciado " << weakPtr.use_count() << " vece(s)\n";
  6.     std::cout << "shared_ptr = " << *miShared << '\n';
  7.   }
  8.   else
  9.   {
  10.     std::cout << "El puntero ha sido eliminado\n";
  11.   }
  12. }
  13.  
  14. int main()
  15. {
  16.   std::weak_ptr<int> weak;
  17.  
  18.   {
  19.     std::shared_ptr<int> shared = std::make_shared<int>(4);
  20.  
  21.     weak = shared;
  22.  
  23.     std::cout << "El puntero esta referenciado " << weak.use_count() << " vece(s)\n";
  24.  
  25.     auto shared2 = shared;
  26.     std::cout << "El puntero esta referenciado " << weak.use_count() << " vece(s)\n";
  27.  
  28.     // Si el puntero está vivo podremos usarlo
  29.     CrearShared(weak);
  30.  
  31.     // Este mensaje muestra como el número de referencias ha bajado porque el shared_ptr
  32.     // que creamos dentro de la función ya no existe
  33.     std::cout << "El puntero esta referenciado " << weak.use_count() << " vece(s)\n";
  34.  
  35.   } // En este punto los dos shared_ptr serán eliminados, eso da lugar a que el puntero
  36.     // se elimine
  37.  
  38.   // Cuando ya no exista el puntero, weak_ptr nos avisará
  39.   CrearShared(weak);
  40. }

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.