2010-05-17 9 views

Antwort

16

Eine weak_ptr enthält eine nicht besitzende Referenz, daher existiert das Objekt, auf das sie sich bezieht, möglicherweise nicht mehr. Es wäre von Natur aus gefährlich, einen rohen Zeiger zu verwenden, der von einer weak_ptr gehalten wird.

Der richtige Ansatz besteht darin, die weak_ptr zu einem shared_ptr mit weak_ptr::lock() zu promoten und den Zeiger davon zu bekommen.

Die Boost weak_ptr documentation erklärt, warum es unsicher wäre, get() Funktionalität als Teil von weak_ptr bereitzustellen, und hat Beispiele für Code, der Probleme verursachen kann.

+0

In diesem Fall können Sie mit einem dangling Zeiger verlassen werden, wenn Sie einen rohen Zeiger für ein 'shared_ptr' erhalten, der auch danach zerstört wird ... im Falle von Multithread können Sie sogar mit einem baumelnden Zeiger im Lauf von verlassen werden der Code 'if (! weak.expired()) weak-> run();' da das Objekt, auf das verwiesen wird, zwischen dem Test und der Ausführung der Methode zerstört werden könnte (ich nehme an, die Methode selbst ist richtig synchronisiert) ... –

+3

@Matthieu: Natürlich können * Sie *, genau wie Sie mit einem dangling Zeiger verlassen können, wenn Sie explizit ein Objekt löschen, aber einen Zeiger darauf behalten. Der Punkt, bei dem ein "weak_ptr" auf "shared_ptr" hochgestuft werden muss, ist, dass es Sie ermutigt, die Verwendung des rohen Zeigers korrekt zu definieren, indem Sie die Regeln befolgen, die Sie normalerweise für 'shared_ptr :: get' verwenden. Es gäbe keinen gleichwertigen Weg, die Verwendung eines rohen Zeigers, der direkt von einem "weak_ptr" erhalten wurde, korrekt zu definieren. –

2

Sie müssen zuerst shared_ptr von weak_ptr ableiten, bevor Sie den rohen Zeiger erhalten.

Sie können lock rufen Sie die Shared_ptr zu bekommen, oder die Shared_ptr Konstruktor:

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

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

Wie geschrieben, ist dies nicht sicher - Sie könnten mit einem baumelnden Zeiger verlassen werden, wenn das Objekt gelöscht wird, wenn das temporäre 'shared_ptr' zerstört wird. Sie sollten den 'shared_ptr' so lange behalten, wie Sie den rohen Zeiger verwenden. –

3

Dies ist eine alte Frage und die akzeptierte Antwort ist gut, so dass ich gerne eine andere Antwort zu schreiben, aber eine Sache, die scheint fehlt, ist ein gutes idiomatisches Verwendungsbeispiel:

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 
} 

ein wesentlicher Vorteil dieses Idioms ist, dass der starke Zeiger auf den if-wahr Block scoped, der ein versehentliches Verwendung einer nicht-initialisierten Referenz oder Aufbewahrung zu verhindern hilft eine starke Referenz um lange äh, als es tatsächlich erforderlich ist.