2017-03-18 23 views
1

我剛剛發現,你可以在C++中做到這一點:如何刪除堆中未存儲到變量指針的對象?

class Line 
{ 
public: 
    Line(int x) : _length(x) {} 
    int GetLength() { return _length; } 
private: 
    int _length; 
}; 

int main() 
{ 
    Line* line = new Line(3); // instead of doing this 
    std::cout << line->GetLength(); 

    std::cout << (new Line(5))->GetLength(); // you can instantiate the object directly without storing it in a pointer 
} 

現在的問題是,代碼,最後一行後,確實有長度= 5的對象獲取堆中立即刪除?如果不是,我們如何刪除它,因爲我們不能使用

delete line; 

像第一個對象的長度= 3。

+6

你已經學會了如何泄漏內存 – AndyG

+2

避免直接使用'new',並且意外地做到這一點變得相當困難。 – chris

回答

3

該對象不會被刪除:對於撥給new的呼叫,沒有相應的呼叫delete。將它分配給pointe然後刪除它並避免內存泄漏。

更好的替代品:

  • 只使用堆棧:Line(5).GetLength()將調用線的析構函數和免費分配的任何內存(在棧上),該行後自動由於暫時未命名的對象超出範圍。
  • 使用std::make_unique<Line>(5)->GetLength()。在這種情況下,這確實在堆上分配了一條new行。 Aterwards,同樣的故事:當這個創建的unique_ptr超出範圍時,它的析構函數會被調用,並且會調用相應的delete
+0

謝謝,夥計。我想我現在要學會聰明的指針。但以某種方式使用堆棧使我困惑。通常情況下,如果超出範圍,堆棧中的對象會自動被刪除嗎?那麼,我怎麼仍然可以像這樣參考: 'for(...){Line line(3); Line * p = &line;}' 'std :: cout << p-> GetLength(); //仍然輸出3!' – Loqz

+0

不應該編譯,因爲p不會在循環之外定義。即使如此,訪問p也是未定義的行爲,因爲它會指向超出範圍的對象。 '未定義的行爲'可以是任何事情,包括意外地給出'預期'的結果。可能是因爲該行所在的內存仍在堆棧中。 – stijn

+0

哎呀,對不起,夥計。它應該是這樣的:'Line * p; (...){直線(3); p = &line;} std :: cout << p-> GetLength();'這個編譯得很好,輸出3. – Loqz

2

恭喜發現「內存泄漏」的概念。

在你的冒險的下一步是瞭解所有關於std::unique_ptrstd::shared_ptrstd::make_uniquestd::make_shared,這將讓你做幾乎同樣的事情,但沒有內存泄漏得到處都是。

而且,作爲額外的獎勵,您再也不必擔心delete什麼。

相關問題