2014-02-15 89 views
1

分配內存,我不小心寫了如下語句的std ::的unique_ptr <T>不上堆

std::unique_ptr<Thing> m_thing; 
m_thing->DoStuff(); 

,而不是

std::unique_ptr<Thing> m_thing(new Thing); 
m_thing->DoStuff(); 

第一示例編譯和運行,這沒有任何意義因爲m_thing不是指向任何對象。這裏有一個稍大的代碼示例。

#include <iostream> 
#include <memory> 
class Thing 
    { 
    public: 
    ~Thing(){ std::cout << "destructor of class Thing\n"; } 
    void DoStuff(){ std::cout << "doing stuff\n"; } 
    }; 

void Foo() 
    { 
    std::unique_ptr<Thing> m_thing; 
    m_thing->DoStuff(); //why does this work, since i suppose m_thing to be empty? 
    } 

int main() 
    { 
    Foo(); 
    std::cout << "after Foo()\n"; 
    std::cin.get(); 
    return 0; 
    } 

爲什麼「empty」m_thing unique_ptr調用Thing類的DoStuff()方法? 我還注意到,該聲明m_thing 與

std::unique_ptr<Thing> m_thing; 

,而不是

std::unique_ptr<Thing> m_thing(new Thing); 

我沒有發現通過谷歌這種行爲作出任何解釋,當事情類的析構函數永遠不會被調用,所以我希望也許有人能向我解釋幕布背後發生的事情。

回答

4

您的程序展示未定義的行爲。 「似乎工作」是未定義行爲的一種可能表現形式。這在道義上相當於

Thing* p = NULL; 
p->DoStuff(); 

我預測它也會編譯和運行。 DoStuff被稱爲NULLthis指針 - 但它實際上並不使用this,這就是爲什麼它不會像您期望的那樣崩潰和燒燬。

4

DoStuff不是虛擬的,不會訪問您的對象的任何成員,所以你可以逃脫調用它(我敢肯定,這是未指定的行爲,雖然)。 unique_ptr的默認構造函數將其初始化爲nullptr,因此它不會自行分配任何內存。

哦,並且析構函數當然不會被調用,因爲unique_ptr不會調用它的刪除器nullptr s。

相關問題