2013-05-28 32 views
1

這是我第一次使用STL,我對如何解除這些容器使用的內存的解除分配感到困惑。例如:處理解析器中的stl容器的解除分配問題

class X { 
    private: 
     map<int, int> a; 
    public: 
     X(); 
     //some functions 
} 

現在讓我們說,我定義構造函數:

X::X() { 
    for(int i=0; i<10; ++i) { 
     map[i]=i; 
    } 
} 

現在的問題是,我應該爲此類編寫或默認C++析構函數將取消分配的護理析構函數內存(完全)?

現在考慮修改上面的類

class X { 
    private: 
     map<int, int*> a; 
    public: 
     X(); 
     ~X(); 
     //some functions 
} 

現在讓我們說,我定義構造函數:

X::X() { 
    for(int i=0; i<10; ++i) { 
     int *k= new int; 
     map[i]=k; 
    } 
} 

現在我明白了,對於這樣一類我需要寫一個析構函數由new分配的內存不能由容器的默認析構函數(因爲它調用在這種情況下是對象的析構函數)來破壞容器。所以,我試圖寫下面的析構函數:

X::~X { 
    for(int i=0; i<10; ++i) { 
     delete(map[i]); 
    } 
    //to delete the memory occupied by the map. 
} 

我不知道如何刪除由map佔用的內存。儘管clear函數在那裏,但它聲稱會將容器的大小降低到0,但不一定會釋放下面的內存。與矢量也是一樣(我猜在STL中有其他容器,但我沒有檢查它們)。

任何幫助表示讚賞。

回答

3

我應該爲這個類編寫析構函數,還是默認的C++析構函數將負責釋放內存(完全)?

是的。所有的標準容器都遵循RAII的原則,並管理自己的動態資源。他們將在銷燬時自動釋放他們分配的任何內存。

我不知道如何刪除地圖佔用的內存。

你不知道。只有當您使用new創建它時,您必須刪除某些內容。大多數對象都會自動分配和釋放內存。

該地圖本身被嵌入在被銷燬的對象中,因此它將被自動銷燬,並且一旦析構函數完成,它的內存將隨着對象的被釋放。

由地圖分配的任何內存都是地圖的責任;它會在它的析構函數中釋放它,這會自動調用。

您只負責刪除動態分配的int對象。由於很難確保您正確刪除這些內容,因此應始終使用RAII類型(如智能指針或地圖本身)來爲您管理內存。 (例如,如果使用new引發異常,則在構造函數中有內存泄漏;通過存儲對象或智能指針而非原始指針可以很容易地修復這個問題。)

+0

那麼答案是明確的,但通過刪除我從來沒有表示'刪除'。我的意思是破壞記憶(否則我會把它放在反引號中)。我的意思是我沒有在STL文檔中看到這樣做的函數。無論如何,謝謝你。 –

+0

@AmanDeepGautam:與任何對象一樣,沒有任何功能來釋放它的內存。對象被銷燬並根據其生命週期釋放內存:自動對象,因爲它們超出範圍,程序結束時的靜態對象以及刪除時的動態對象。 –

+0

這就是讓我困惑的原因。我現在明白了。謝謝。 –

1

如果你忽略了你正在處理的容器的類型,只要將它看作一個容器,就會注意到你放入容器的任何東西都由擁有該容器的人擁有。這也意味着所有者必須刪除該內存。您的方法足以釋放您分配的內存。由於地圖對象本身是一個堆棧分配的對象,所以它的析構函數會自動調用。

或者,這種情況的最佳做法是使用shared_ptr或unique_ptr,而不是原始指針。這些包裝類將自動爲您解除分配內存。

map<int shared_ptr<int>> a; 

參見http://en.cppreference.com/w/cpp/memory

1

當STL集合被破壞,所包含的對象的相應的析構函數被調用。

這意味着,如果你有

class YourObject { 
    YourObject() { } 
    ~YourObject() { } 
} 

map<int, YourObject> data; 

隨後的YourObject調用析構函數。

在另一方面,如果你是存儲指向對象像

map<int, YourObject*> data 

然後將鼠標指針的自毀被調用,從而釋放指針本身,但沒有調用構造函數尖。

解決方案是使用一些可以容納對象的東西,比如shared_ptr,這是一個特殊的對象,在沒有更多引用時它會關心調用Holded對象。

例子:

map<int, shared_ptr<YourObject>> 
0

簡短的回答是,容器通常會採取刪除其內容當容器本身被破壞的照顧。

它通過銷燬容器中的對象來實現這一點。因此,如果你想足夠糟糕,可以通過分配內存(例如,在其ctor中)創建一個管理不善的類型,但不能正確釋放內存。這顯然應該通過糾正這些對象的設計來解決(例如,添加釋放他們擁有的內存的dtor)。或者,您也可以通過存儲原始指針來獲得相同的效果。

同樣,您可以創建一個無法正常工作的分配器 - 分配的內存但在請求釋放內存時什麼都不做。

在每一種情況下,真正的答案是「只是不這樣做」。

0

如果必須編寫析構函數(或cctor或op =)它表明你可能做錯了什麼。如果你這樣做更容易釋放資源。

異常是資源的RAII處理程序,除此之外別無其他。

在常規課程中,您使用適當的成員和基類,因此您的dtor沒有自己的工作。

STL類都處理自己,所以有一張地圖你沒有義務。除非你用啞指針指向分配的內存或類似的東西 - 第一個觀察點在哪裏。

如果在第五個新的函數中引發了異常,則第二個X :: X()你泄漏了第一個4.如果你想用手處理這個情況,你會得到一堆代碼。
如果你使用正確的聰明的東西,比如unique_ptr或shared_ptr而不是int *,那麼這一切都可以避免。