2016-04-16 6 views
1

Ist der folgende Code zulässig? Meine Sorge ist die Verwendung der .release Methode, nachdem das Objekt in der Start Methode zerstört worden ist.Freigabe eines unique_ptr, nachdem das Objekt zerstört wurde

class Foo 
{ 
public: 
    Foo() 
    { 
     std::cout << "Foo ctor\n"; 
    } 

    ~Foo() 
    { 
     std::cout << "Foo dtor\n"; 
    } 

    void Start() 
    { 
     std::unique_ptr<Foo> ptr(this); 
    } 
}; 

int main(int argc, char* argv[]) 
{ 
    auto ptr = std::make_unique<Foo>(); 
    ptr->Start(); 
    ptr.release(); 
} 

Ich versuchte dies in vs12 und es hat sich nicht beklagen.

+0

die perfekte Weg, um das eigene Bein zu schießen – user3159253

+0

temporäre Instanz in 'Start()' wird zerstört werden, wenn 'Start()' abgeschlossen ist, im Wesentlichen löschen 'this' – user3159253

+0

Da der Zeiger ist' release() 'd unmittelbar danach, nichts besonders gefährlich passiert, aber zwischen 'ptr-> Start()' completion und 'ptr.release()' invocation 'ptr' besitzt das zerstörte Objekt, das definitiv co führen zu Abstürzen und Speicherbeschädigungen. – user3159253

Antwort

2

std :: unique_ptr ist ein Container für einen Zeiger mit nur einer Aktion: Löschen der Instanz, auf die sie verweist, wenn sie zerstört wird. (oder wenn reset() aufgerufen wird)

Solange der Destruktor oder die Reset-Funktion nicht aufgerufen wird, haben Sie Code, der ausgeführt wird. Wenn Sie jedoch die Start() -Funktion so umschreiben, dass auch eine Ausnahme ausgelöst wird, erhalten Sie einen Absturz. (Ohne zusätzlichen Catch-Code) Ein weiteres Risiko besteht darin, dass Sie in Ihrem Programm einen baumelnden Zeiger behalten, auf den Sie achten müssen.

Also ja, Ihr Code ist legal und gültig, obwohl ich es nicht empfehlen würde, da es fehleranfällig ist. Ich würde eher empfehlen, etwas zu schreiben, wie:

static void Start(std::unique_ptr<Foo> &&owner) 
{ 
std::unique_ptr<Foo> ptr(std::move(owner)); 
} 

Oder wenn Sie wirklich das Eigentum innerhalb dieser Methode müssen (sie Threads betrachten), so dass es einen std :: shared_ptr und das Eigentum teilen:

class Foo : std::enable_shared_from_this<Foo> 
{ 
    void Start() 
    { 
    std::shared_ptr<Foo> ptr = shared_from_this(); 
    } 
}