2010-05-17 10 views

Respuesta

16

A weak_ptr contiene una referencia no propietaria, por lo que el objeto al que se refiere puede que ya no exista. Sería intrínsecamente peligroso utilizar un puntero sin procesar en un weak_ptr.

El enfoque correcto es promocionar weak_ptr a shared_ptr usando weak_ptr::lock() y obtener el puntero de eso.

El Boost weak_ptr documentation explica por qué no sería seguro proporcionar get() funcionalidad como parte de weak_ptr, y tiene ejemplos de código que pueden causar problemas.

+0

De hecho, puede dejar un puntero colgante si obtiene un puntero sin formato para un 'shared_ptr' que también se destruye después ... en caso de Multithread puede incluso dejar un puntero colgando en la ejecución de el código 'if (! weak.expired()) weak-> run();' como el objeto apuntado podría destruirse entre la prueba y la ejecución del método (supongo que el método está sincronizado correctamente) ... –

+3

@ Matthieu: por supuesto * puede *, del mismo modo que puede dejar un puntero colgante si 'elimina' explícitamente un objeto pero mantiene un puntero al mismo. El punto de tener que promocionar un 'weak_ptr' a' shared_ptr' es que lo alienta a que alcance correctamente el uso del puntero sin formato, siguiendo las reglas que normalmente usa para 'shared_ptr :: get'. No habría una forma equivalente de delimitar correctamente el uso de un puntero sin formato obtenido directamente de un 'weak_ptr'. –

2

Primero debe derivar el shared_ptr del weak_ptr antes de obtener el puntero sin formato.

Puede llamar lock para obtener el shared_ptr, o el constructor shared_ptr:

boost::weak_ptr<int> example; 
... 

int* raw = boost::shared_ptr<int>(example).get(); 
+8

Tal como está escrito, esto no es seguro: podría quedar con un puntero colgante si el objeto se elimina cuando se destruye el 'shared_ptr' temporal. Debes mantener presionado el 'shared_ptr' mientras uses el puntero sin formato. –

3

Ésta es una vieja pregunta y la respuesta aceptada es bueno, por lo que dudó en publicar otra respuesta, pero una cosa que parece falta es un buen ejemplo de uso idiomático:

boost::weak_ptr<T> weak_example; 
... 
if (boost::shared_ptr<T> example = weak_example.lock()) 
{ 
    // do something with example; it's safe to use example.get() to get the 
    // raw pointer, *only if* it's only used within this scope, not cached. 
} 
else 
{ 
    // do something sensible (often nothing) if the object's already destroyed 
} 

una ventaja clave de este lenguaje es que el puntero fuerte tiene como alcance el bloque si-verdadero, lo que ayuda a evitar el uso accidental de una referencia no inicializado, o posesión una referencia fuerte alrededor de larga de lo que realmente se requiere.

Cuestiones relacionadas