2016-03-14 73 views
0

前些日子,我正要問一個相當簡單的初學者問題,當我意識到我沒有爲我的函數釋放內存時,我正在處理一個C++函數。這似乎永遠不會在這裏結束。在函數中釋放內存

看起來這將是一個共同的問題,但我沒能在在C我的瞭解程度++

發現了什麼我怎麼會在這個代碼

#include <iostream> 

class thing{ 
    public: 
    int a; 
    }; 

thing makeThing(){ 
    thing *t = new thing; 
    t -> a = 5; 
    return *t; 
    } 

int main(){ 
    thing thing1 = makeThing(); 
    std::cout << "a: " << thing1.a << std::endl; 
    return 0; 
    } 

由於正常可用內存據我所知,在函數終止後我無法釋放它。 我嘗試這樣做:

delete &thing1; 

而是基於核心轉儲,我認爲不是這樣做的方式。

+0

「makeThing」中存在內存泄漏問題 –

+0

我該如何解決?這種編碼方式直接出自我的教科書,所以我不知道有什麼不同的方式。 – mreff555

+2

如果這出來你的教科書,然後開始使用它的更好的目的。用它擦拭你的底部?! –

回答

3

既然你的價值回報,這意味着你返回對象的一個​​副本。原函數由new things創建,函數返回後無法到達(不可靠)。

您可以返回一個指針:

thing* makeThing(){ 
    thing *t = new thing; 
    t -> a = 5; 
    return t; 
} 

和刪除。

但是你應該真的只是返回一個對象,在這種情況下甚至不會分配任何與new

+0

這是有道理的。謝謝Lucian,我讓這個函數成爲一個指針,現在我可以調用並釋放它。 – mreff555

3

有時以釋放內存最簡單的方法是沒有分配它開始:

thing makeThing(){ 
    thing t; 
    t.a = 5; 
    return t; 
} 

你正在試圖做不工作什麼的原因是,當你有:

delete &thing1; 

這就是你的本地對象的地址......這不是你實際分配的地址。那個被複制到你的,現在你無法訪問它。

如果你想分配你的thing,你需要直接返回指針。優選地,包裹不知何故:

std::unique_ptr<thing> makeThing() { 
    std::unique_ptr<thing> t(new thing); 
    t->a = 5; 
    return t; 
} 
+0

優秀的答案來自一個美妙的名字的神奇人物。 –

+0

@BarryTheHatchet Swoon。 – Barry

1
thing makeThing(){ 
    thing *t = new thing; 
    t -> a = 5; 
    return *t; 
    } 

引出立即內存泄漏。在makeThing()返回後,t變量將超出範圍,並且分配的內存將永遠不會被釋放,也不會被適當的delete語句釋放。

返回新創建的t的副本。

要修復它只是創造一個局部變量和retun副本:

thing makeThing(){ 
    thing t; 
    t.a = 5; 
    return t; 
} 
0

如果你真的想用new這是正確的做法。這段代碼是C++ 11,所以如果在你使用的編譯器中它不是默認的話,你可能需要打開一些選項。我習慣使用C++ 11,因爲這種語言版本的改進是非常值得的。

#include <iostream> 
#include <memory> 
#include <ostream> 

class thing { 
public: 
    int a; 
}; 

std::ostream& operator<<(std::ostream& os, const thing& t) { 
    os << t.a; 
    return os; 
} 

std::unique_ptr<thing> makeThing() { 
    std::unique_ptr<thing> t(new thing); 
    t->a = 5; 
    return std::move(t); 
} 

int main() { 
    auto thing1 = makeThing(); 
    std::cout << "a: " << *thing1 << std::endl; 
    return 0; 
} 

但實際上如果你想要做的只是創建一個對象,那麼就不需要在堆上分配它。你可以像下面的代碼那樣做。請注意,該對象是在不使用new的情況下創建的。該對象在從makeThing()返回時被複制,並且編譯器使用class thing(我沒有替換)的默認拷貝構造函數。

#include <iostream> 
#include <ostream> 

thing makeThing() { 
    thing t; 
    t.a = 5; 
    return t; 
} 

int main() { 
    auto thing1 = makeThing(); 
    std::cout << "a: " << thing1 << std::endl; 
    return 0; 
} 

ostream插件不需要改變,所以我省略了它。類定義相同。

+0

謝謝詹姆斯。我意識到可以這樣做,但如果我在運行時嘗試添加大量對象並設置了許多變量,我不會這樣做嗎? – mreff555

+0

不一定..例如,您可以在像'std :: vector'這樣的數據結構中擁有數百萬或數十億個'class thing'的實例,而無需使用'new'。當然,'std :: vector'的實現可能會在內部使用新的。 –

+0

對。向量似乎處理所有的內存管理,但我正在通過一個教程來製作一個二叉樹(學習目的),並跑過去。 – mreff555