2013-03-21 126 views
0

在下面的代碼中,drvdCls派生自bseCls。此代碼編譯並按原樣運行。然而,我在這裏發現一個問題:在Test()退出後,newBse將被釋放。我對嗎?基礎和派生類分配

bseCls* Test() 
{ 

    bseCls* newBse = new drvdCls(); 
    drvdCls newDrvd; 
    newBse = &newDrvd; 
    return newBse; 

} 
+0

不,它不會。這是動態內存分配的重點。但是,在代碼中存在嚴重的問題 - 您將指針指向已分配的內存,並返回一個指向自動變量的指針(在func退出時將釋放此指針,最終將解決函數調用器中釋放的內存)。 – SomeWittyUsername 2013-03-21 16:08:58

+0

@icepack'newBse'只是一個指針,當它返回時它指向一個局部變量。 – juanchopanza 2013-03-21 16:10:26

+0

@juanchopanza這是正確的,但這不是被問到的問題 – SomeWittyUsername 2013-03-21 16:11:43

回答

0

你有兩個危險的缺陷

  • drvdCls newDrvd;聲明在棧上的局部對象,並從函數返回後,它就會被破壞。那麼指向newDrvdnewBse將無效。

  • &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 
} 
4

對象最初指向newBse會被泄露。當您將地址newDrvd分配給newBse時,您將丟失指向堆分配對象的指針,並且您將無法使用delete它。這個內存將不可用,直到進程終止。

  1. 對象的析構函數將被該函數返回前調用,這意味着你會:

    此外,您作爲一個指針,這是壞的原因有兩個返回堆棧分配對象的地址使用一個指向被破壞對象的指針。

  2. 爲對象分配的內存位於堆棧上,幾乎肯定會被未來的函數調用破壞。那時候,你的指針會指向一個不是bseCls的東西,但你會像使用它一樣。

如果您使用此函數返回的指針,要調用未定義的行爲和你的程序有牌做任何事情

1

不,它不會被自動解除分配。致電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超出範圍。

+0

請注意'std :: unique_ptr <>'只能從C++ 11開啓。根據這個函數的使用方式,'std :: auto_ptr <>'或'boost :: shared_ptr <>'對於較老的C++版本來說是一個很好的選擇。 – cdhowie 2013-03-21 17:12:26