2013-09-25 76 views
2

我用new Time(1,0,0)初始化SmartPtr類。什麼時候用`new`創建的臨時對象調用'delete'?

//main.cpp 
    int main() 
{ 
    SmartPtr pTime0(new Time(0,0,1)); 
} 

我在哪裏打電話刪除new Time(1,0,0)。一切正常,程序符合並運行。但我很困惑 - 我該在哪裏/不應該delete Time(1,0,0)

我不明白在這裏創建和刪除臨時對象的概念。 我知道每當我寫new某處我必須寫delete! 有人可以解釋delete Time(1,0,0)發生在哪裏嗎?

SmartPtr pTime0(new Time(0,0,1))< - new這裏返回一個指向新分配的內存的指針,然後在ctor中我第二次分配內存new

//SmartPtr.cpp 

SmartPtr::SmartPtr(Pointee * p):_pointee(new Pointee(*p)) 
{} 

SmartPtr::~SmartPtr() 
{ 
    delete _pointee; 
} 
+0

的SmartPtr是你自己設計的一類?它可以很好地管理對象的生命週期,在這種情況下,類決定何時刪除。 –

+5

我不明白你爲什麼要在SmartPtr的ctor的堆上創建一個新的Pointee。這不是你想要的。你應該簡單地寫'_pointee(p)',即簡單地使用與給定的相同的指針。您的聲明將分配一個新的Pointee並將提供的指針的內容複製到它。 – leemes

+0

我不想'_pointee(p)'。如果p(new Time(0,0,1))在我的類的外部創建,那麼它可能會被刪除('delete p'),而我的SmartPtr析構函數也會'delete _pointee'(初始化爲p )',所以會導致運行時錯誤。我試圖實現的概念是在ctor中分配內存並在dtor中刪除它。 – Oleksandra

回答

2

我不知道你的SmartPtr類的細節。

在任何情況下,如果你有這樣的構造:

SmartPtr::SmartPtr(Pointee * p):_pointee(new Pointee(*p)) 
{} 

,這是析構函數:

SmartPtr::~SmartPtr() 
{ 
    delete _pointee; 
} 

然後用這個代碼:

SmartPtr pTime0(new Time(0,0,1)); 

您泄露了Time(0,0,1)的一個實例。

事實上,你有一個更newdelete(2 new秒和1 delete):

第1步:你叫new Time(0,0,1)並在堆上創建一個新的對象。
new計數== 1)

步驟#2:你傳遞這個指針SmartPtr構造函數,它深層副本先前創建的對象,並分配在堆上一個新的副本,並且經由保持該拷貝的軌道其_pointee數據成員。
new計數== 2)

步驟#3:當SmartPtr析構運行時,它delete S中的例如通過_pointee數據成員指出,但你泄漏的firts Time(...)new Time(0,0,1)在堆上創建。
delete計數== 1; new計數== 2)

對於一個可能的修復可能只是有這樣的構造:

SmartPtr::SmartPtr(Pointee * p) 
    : _pointee(p) // <--- transfer ownerhsip (no deep copies) ! 
{} 

一個簡單的方法來識別潛在的泄漏這些情況是在Time類的構造函數和析構函數中放入一些控制檯跟蹤輸出,並檢查析構函數的跟蹤輸出是否與構造函數匹配,例如:

Time::Time(....) 
{ 
    // Do construction work.... 

    std::cout << "Time constructor\n"; 
} 

Time::~Time(....) 
{ 
    // Do destructor work.... 

    std::cout << "Time destructor\n"; 
} 

字符串的總計數應該與"Time destructor"字符串的總計數相匹配"Time constructor"

+0

//main.cpp SmartPtr ptTime(new Time(0,0,1));給出以下內容: Time ctor(0,0,1) SmartPtr ctor SmartPtr dtor Time dtor(0,0,1)。爲什麼程序不會中止?如果是內存泄漏 – Oleksandra

+0

對於日誌記錄,不要忘記複製構造函數。 – Jarod42

+0

ctors的數量(無論是複製或默認還是其他)應該與析構函數的數量相匹配?如果是這樣的話,的確我有Time Ctor,Time copy Ctor,SmartPtr Ctor,SmartPtr Dtor,並且只有1個時間析構函數! – Oleksandra

0

表達new Time(0,0,1)創建臨時指針在堆上一個永久對象。臨時指針確實會被自動銷燬(這是一個無操作),將對象留在堆上但未被引用。發生泄漏。

爲了防止泄漏,請確保將指針存儲在某個地方,並確保最終對其進行調用。

1

兩種方法來解決:

方法A,來電分配,的SmartPtr取得所有權:

SmartPtr::SmartPtr(Pointee * p):_pointee(p) 
{ 
} 

方法B,來電提供的內容及的SmartPtr分配:

SmartPtr::SmartPtr(Pointee v):_pointee(new Pointee(std::move(v))) 
{ 
} 

和析構函數保持不變:

SmartPtr::~SmartPtr() 
{ 
    delete _pointee; 
} 
0

您可以根據原則編寫您的應用程序永不鍵入新的
與現有的智能指針結合這一點,就變成:

#include <memory> // this is where the smart-pointers live 
#include "Time.h" // or whatever header defines your "Time" class 

int main() 
{ 
    // note that make_shared is essentially a forwarding constructor, 
    // give it whatever parameters Time's constructor would take 
    auto p = std::make_shared<Time>(0,0,1); 
    // use p here 
} 

而且不會有任何東西永遠泄漏。

「永不輸入新的」應該應用於所有應用程序編程, 唯一的例外是,如果您必須編寫低級 資源管理庫。

請注意,如果一個類做資源管理,它應該是它的唯一功能 。

所有其他類應遵循rule of zero

相關問題