在下面的代碼中,drvdCls
派生自bseCls
。此代碼編譯並按原樣運行。然而,我在這裏發現一個問題:在Test()
退出後,newBse
將被釋放。我對嗎?基礎和派生類分配
bseCls* Test()
{
bseCls* newBse = new drvdCls();
drvdCls newDrvd;
newBse = &newDrvd;
return newBse;
}
在下面的代碼中,drvdCls
派生自bseCls
。此代碼編譯並按原樣運行。然而,我在這裏發現一個問題:在Test()
退出後,newBse
將被釋放。我對嗎?基礎和派生類分配
bseCls* Test()
{
bseCls* newBse = new drvdCls();
drvdCls newDrvd;
newBse = &newDrvd;
return newBse;
}
你有兩個危險的缺陷
drvdCls newDrvd;
聲明在棧上的局部對象,並從函數返回後,它就會被破壞。那麼指向newDrvd
的newBse
將無效。
將&newDrvd
指定給newBse
後發生內存泄漏。
讓我們來仔細看看:
bseCls* Test()
{
bseCls* newBse = new drvdCls(); // Allocates memory, newBse points to it
drvdCls newDrvd; // Allocates memory on local stack
newBse = &newDrvd; // newBse points to newDrvd (losts previous link - leak)
return newBse; // returns pointer to somewhere which is destroying
}
對象最初指向newBse
會被泄露。當您將地址newDrvd
分配給newBse
時,您將丟失指向堆分配對象的指針,並且您將無法使用delete
它。這個內存將不可用,直到進程終止。
此外,您作爲一個指針,這是壞的原因有兩個返回堆棧分配對象的地址使用一個指向被破壞對象的指針。
bseCls
的東西,但你會像使用它一樣。如果您使用此函數返回的指針,要調用未定義的行爲和你的程序有牌做任何事情。
不,它不會被自動解除分配。致電new
的每個電話都必須與致電delete
的電話相匹配。但是這不是你的代碼唯一的問題,你還要從函數返回一個局部變量的地址。
newBse = &newDrvd; // memory leak, pointer to previously allocated object is lost
return newBse; // newDrvd is destroyed when function exits, so returned
// pointer points to invalid memory
什麼你可能想要做的就是
bseCls* Test()
{
return new drvdCls();
}
現在,調用者必須使用它後調用delete
對返回的指針。你應該做的是
std::unique_ptr<bseCls> Test()
{
return new drvdCls();
}
現在分配的對象將自動delete
d時,返回的unique_ptr
超出範圍。
請注意'std :: unique_ptr <>'只能從C++ 11開啓。根據這個函數的使用方式,'std :: auto_ptr <>'或'boost :: shared_ptr <>'對於較老的C++版本來說是一個很好的選擇。 – cdhowie 2013-03-21 17:12:26
不,它不會。這是動態內存分配的重點。但是,在代碼中存在嚴重的問題 - 您將指針指向已分配的內存,並返回一個指向自動變量的指針(在func退出時將釋放此指針,最終將解決函數調用器中釋放的內存)。 – SomeWittyUsername 2013-03-21 16:08:58
@icepack'newBse'只是一個指針,當它返回時它指向一個局部變量。 – juanchopanza 2013-03-21 16:10:26
@juanchopanza這是正確的,但這不是被問到的問題 – SomeWittyUsername 2013-03-21 16:11:43