2010-12-13 20 views
10

Ich bin nur mit den intelligenten Zeigern in der bevorstehenden neuen C++ Standard herumspielen. Allerdings verstehe ich die Verwendung der Funktion shared_from_this nicht. Hier ist, was ich habe:enable_shared_from_this (C++ 0x): Was mache ich falsch?

#include <iostream> 
#include <memory> 

class CVerboseBornAndDie2 : public std::enable_shared_from_this<CVerboseBornAndDie2> 
{ 
public: 
    std::string m_Name; 
    CVerboseBornAndDie2(std::string name) : m_Name(name) 
    { 
     std::cout << m_Name << " (" << this << ") is born!" << std::endl; 
    } 
    virtual ~CVerboseBornAndDie2() 
    { 
     std::cout << m_Name << " (" << this << ") is dying!" << std::endl; 
    } 
}; 

int main(){ 
    CVerboseBornAndDie2* vbad = new CVerboseBornAndDie2("foo"); 
    std::shared_ptr<CVerboseBornAndDie2> p = vbad->shared_from_this(); 
} 

und es wirft eine std :: bad_weak_ptr Ausnahme in der Linie

std::shared_ptr<CVerboseBornAndDie2> p = vbad->shared_from_this(); 

wenn ich stattdessen tun

std::shared_ptr<CVerboseBornAndDie2> p(vbad); 

es funktioniert und ich kann danach tun

std::shared_ptr<CVerboseBornAndDie2> p2 = p.get()->shared_from_this(); 

so muss das Objekt zu einem shared_ptr gehören, bevor ich shared_from_this verwenden kann? Aber wie kann ich das vorher wissen?

Antwort

22

Es ist eine Voraussetzung für die Verwendung shared_from_this, dass mindestens eine shared_ptr vorhanden sein muss, die das betreffende Objekt besitzt. Das bedeutet, dass Sie shared_from_this nur verwenden können, um eine shared_ptr abzurufen, die ein Objekt besitzt, auf das Sie eine Referenz oder einen Zeiger haben. Sie können nicht verwenden, um herauszufinden, ob ein Objekt einer shared_ptr gehört.

Sie müssen Ihr Design so überarbeiten, dass entweder garantiert ist, dass ein solches Objekt von einer shared_ptr verwaltet wird oder dass Sie es nie wissen müssen oder dass Sie (oder am wenigsten wünschenswert) eine andere Art der Verwaltung erstellen dieses Wissen.

+0

Konnten Sie nicht einfach einen try-Block um einen Aufruf von shared_from_this setzen, wenn Sie herausfinden wollten, ob das Objekt von einem shared_ptr gehalten wird? Ich weiß nicht, wie es im (kommenden) Standard spezifiziert ist, aber es scheint kein undefiniertes Verhalten zu sein - es wirft eine Ausnahme auf. – nobar

+1

@nobar: Dies wäre inferently unsicher. Sie würden sich auf undokumentierte Implementierungsdetails verlassen. 'shared_from_this' ist keine Methode zum Testen, ob ein Objekt einem gemeinsamen Zeiger gehört; es ist eine Methode zum Abrufen eines geteilten Zeigers von einem Objekt, dem Sie _know_ im Besitz eines gemeinsamen Zeigers sind. –

+0

Ich denke, du hast Recht. Der C++ 0x-Entwurf besagt: "Es muss mindestens eine shared_ptr-Instanz geben, die & t. Besitzt." Sie sagt jedoch nicht, was sonst passiert. Es zeigt eine Implementierung in Bezug auf weak_ptr (was bedeuten würde, dass eine Exception bei einem Fehler ausgelöst wird), aber das ist nur ein "Vorschlag". Ich frage mich, ob die Fehlerbehandlung eventuell besser spezifiziert wird. – nobar

15

Um Charles Antwort zu erweitern, wenn Sie enable_shared_from_this verwenden möchten Sie normalerweise etwas wie unten, um zu garantieren, dass es ein shared_ptr gibt.

class my_class : public std::enable_shared_from_this<my_class> 
{ 
public: 
    static std::shared_ptr<my_class> create() // can only be created as shared_ptr 
    { 
     return std::shared_ptr<my_class>(new my_class()); 
    } 
private 
    my_class(){} // don't allow non shared_ptr instances. 
}; 
+1

'create()' sollte 'static' sein, oder? –

+0

@ Abyss.7: In der Tat. – ronag

+1

Und um die Freigabe standardmäßig zu haben, könnten Sie etwas wie folgt verwenden: 'try {return shared_from_this(); } catch (const bad_weak_ptr &) {return make_shared (); } ' –