2010-09-30 21 views
6

¿Por qué no puedo hacer esto?Boost asignación Shared_Ptr

boost::shared_ptr<QueuList> next; 

void QueuList::SetNextPtr(QueuList* Next) 
{ 
    boost::mutex mtx; 

    boost::mutex::scoped_lock lock(mtx); 
    {// scope of lock 
     //if (next == NULL) // is this needed on a shared_ptr?? 
     next = Next; // Why can I not assign a raw ptr to a shared_ptr???? 
    } 

}

¿Cómo debería hacerlo en su lugar ??

EDITAR: Llamar a este método cuando la siguiente variable se asigna correctamente, todavía causa un error cuando el objeto QueuList se destruye por algún motivo. Obtengo una afirmación de depuración. El destructor del objeto no hace nada en particular. Sólo se bloquea cuando llamo a esta función:

QueuList li; 
    QueuList lis; 

    li.SetNextPtr(&lis); 

Cuando principal está fuera de ámbito, recibo una aserción de depuración ... ¿Alguna idea ??

+1

editado mi respuesta para su edición. –

Respuesta

5

Poner un puntero dentro de una propiedad shared_ptr transferencias del puntero a la shared_ptr, por lo que el shared_ptr es responsable de eliminarlo. Esto es conceptualmente una operación importante, por lo que los diseñadores de shared_ptr no querían que simplemente sucediera como parte de una asignación de aspecto normal. Por ejemplo, querían evitar que un código como:

some_shared_ptr = some_other_smart_pointer.get(); 

que se parece bastante inocuo, pero significaría que ambos punteros inteligentes pensaban que tenían la responsabilidad de limpiar el puntero, y probablemente doble eliminar el puntero o algo similar .

Esto es lo que está sucediendo con su aserción de depuración. Llamar al SetNextPtr(&lis) pasa propiedad de &lis al shared_ptr, y "propiedad" significa que el shared_ptr llamará al delete en su punta cuando la última copia del shared_ptr quede fuera del alcance. Así que está eliminando efectivamente una variable local (pila) - lis - que corrompe la pila y provoca el bloqueo.

+0

así que si lis es un puntero en sí, pasarlo a esta función hará que sea propiedad de shared_ptr o ¿tendré que borrar mi puntero lis? –

+0

No necesitará eliminar el puntero 'lis'; solo necesita' borrar' los punteros obtenidos de 'new', y de hecho debe * solo * invocar' delete' en los punteros que fueron devueltos por 'new'. Es incorrecto pasar el puntero 'lis' a esta función, ya que la función actualmente está escrita, porque '& lis' no es un puntero obtenido de' new', y la función implícitamente 'borrará' su argumento. – Doug

+0

Estaba hablando de un puntero como este: QueuList * lis = new QueuList(); –

7

Esto se hace para evitar asignar accidentalmente punteros a un shared_ptr cuya vida útil se gestiona de forma independiente. Debe crear explícitamente un shared_ptr que luego tome posesión del objeto.

next = boost::shared_ptr<QueueList>(Next); 

Editar acerca de su edición El problema es que en el caso de que el shared_ptr asume la propiedad de un objeto en la pila. A continuación, pueden ocurrir dos cosas:

  1. La pila marco del objeto se limpia antes de la shared_ptr alcanza un recuento de referencia de 0. En ese caso, el shared_ptr tratarán de eliminar un objeto no existe en algún lugar más adelante, lo que lleva a un comportamiento indefinido.
  2. El shared_ptr alcanza un recuento de referencia de 0 antes de borrar el marco de pila. En ese caso, intentará eliminar un objeto en la pila. No sé exactamente qué sucede en ese caso, pero supongo que también es un comportamiento indefinido.
+5

O simplemente use la función Restablecer miembro - 'a continuación.reset (Next); ' –

6

Puede utilizar la función de reposición() en lugar de la más prolijo next = boost::shared_ptr<QueueList>(Next);

next.Reset(Next); 
Cuestiones relacionadas