2010-07-27 413 views
13

我搜索了StackOverflow,但找不到這個問題的答案。在C++中釋放std :: vector指針的正確方法是什麼?

假設我有一個std::vector<Day *> vector_day - 即 - 指向Day對象的指針向量。現在我push_backvector_day許多元素:

vector_day.push_back(new Day(12)); 
vector_day.push_back(new Day(99)); 
vector_day.push_back(new Day(71)); 
... 

現在在某些時候我不再需要vector_day。什麼是釋放內存的正確方法?

這一點,正確的方法:

for (std::vector<Day *>::iterator i = vector_day.begin(); i != vector_day.end(); ++i) { 
    delete *i; 
} 

這是否失效每個缺失載體?我很困擾。

+0

可能http://stackoverflow.com/questions/3054567/right-way-to-deallocate-an-stdvector-object – 2010-07-27 15:07:56

+0

RC愚弄的人 - 不是真的,這是完全不同的。 – bodacydo 2010-07-27 15:14:09

+1

不要像這樣放入指針。如果在矢量中的東西與刪除它的地方之間引發異常,該怎麼辦?你會跳過它並泄漏。使用智能指針或指針容器,從不使用原始指針。 – GManNickG 2010-07-27 16:40:32

回答

16

最好的方法是不要把指針放在第一位,如果你不是絕對需要的話。

但是,如果你真的需要有一個指針向量,那麼你這樣做的方式就好了(但是.clear()向量後綴,如果它不會立即銷燬,所以它沒有充滿懸掛指針)

聲明

delete *it; 

對迭代器沒有影響。它不會更改迭代器,使迭代器失效或從集合中刪除迭代器引用的指針。它所做的就是釋放迭代器引用的指針所指向的內存。指針本身必須單獨從集合中刪除。

+0

感謝您的解釋。所以當向量超出範圍時,指針將被自動刪除,是嗎? – bodacydo 2010-07-27 15:11:59

+1

@bodacydo:對。如果你在'vector'超出範圍之前進行'delete * it'調用,不用擔心調用'clear()'。 – 2010-07-27 15:34:24

0

從數組中添加或刪除元素的操作可能會使迭代器失效,請檢查文檔以獲取不同容器類型的特定規則。使用delete時,您正在處理包含在數組元素中的數據,而不是數組的形狀。迭代器遍歷容器的形狀,他們不關心其內容。

+0

我現在更好地理解失效。感謝您的回答! – bodacydo 2010-07-27 15:13:42

0

首先,你從i切換到it,但我認爲這只是一個錯字。

但是要回答你的任務,不,那很好。你沒有改變it,你正在改變*it

+0

我改正了'it'用於'i'的錯誤。感謝您的發現。 如果我在循環中做了'i = 0xAABBCCDD'會怎麼樣 - 這明顯改變了'i'而不是'it',會使矢量無效? – bodacydo 2010-07-27 15:13:02

1

您應該使用某種託管指針,最有可能是共享指針。

如果你在別人仍然堅持其中一個指針的時候刪除了這個向量,那麼如果他們試圖對其進行解引用,你會得到一些非常討厭的行爲。共享指針將爲您節省頭痛。

如果你可以保證在矢量被刪除後沒有別的東西會引用指針,那麼你仍然可以從使用自動指針中受益。當矢量被銷燬時,它將爲你管理釋放。開銷很小,而且讓你的生活更輕鬆。

+0

我會去unique_ptr,當然不是auto_ptr。 – Gabriel 2013-01-12 09:07:30

0

這很好。您正在刪除*i(矢量的元素指向的對象),而不是i(矢量的元素),所以矢量不會失效。

請參閱this question的情況下,開發商也想刪除所有i s,併爲其解決方案(vector_day.clear())循環後。

3

另一個C++的方式來做到這一點是定義一個輔助結構:

struct delete_ptr { // Helper function to ease cleanup of container 
    template <typename P> 
    void operator() (P p) { 
     delete p; 
    } 
}; 

,然後使用算法:

std::for_each(vector_day.begin(), vector_day.end(), delete_ptr()); 
vector_day.clear(); 
2

一般在C++中,你應該隱藏的內存管理,儘可能以避免內存錯誤。除非你做了大量的指針複製,並且關心性能,否則我只會使用shared_ptr。

它是TR1標準的一部分,可在大多數現代C++編譯器中使用(http://anteru.net/2008/09/01/260/),非常適合火災和忘記內存管理。

+1

或者首先你應該看看unique_ptr。 – DanDan 2010-07-27 16:17:57

5

Boost ptr_vector來救援!

不正是你所需要的,而不需要重複和刪除性病的內容:: vector的

0

這裏有一個方便的類我前一段時間寫在處理同樣的問題。我將一些基於舊RogueWave向量和列表的代碼轉換爲基於STL的向量和列表,並且需要一些方法來模擬RW的指針列表clearAndDestroy()方法。可以重寫clearAndDestroy()方法來處理不同的結構類型(爲簡潔起見,我只在這裏包含向量)。

class StlUtils 
{ 
    public: 

     /** 
     * This method provides a templated way to destroy a std::vector 
     * full of pointers. It is basically a replacement for the RW 
     * vector class' clearAndDestroy methods. The list argument is 
     * returned empty. 
     * 
     * @param list the list of pointers to be destroyed. 
     */ 
     template<class T> static void clearAndDestroy(
     std::vector<T*> &itemList) 
     { 
     for_each(itemList.begin(), itemList.end(), 
        stl_deleter<T>()); 
     itemList.clear(); 
     } 

    private: 

     /** 
     * Templated member function for use with the clearAndDestroy() 
     * method. It provides the method needed by for_each to do the 
     * actual deletion. 
     */ 
     template<class T> struct stl_deleter 
     { 
     void operator() (T* x) { 
      if (x != NULL) 
       delete x; 
     } 
     }; 
}; 
+0

你可以刪除空指針(它什麼也不做),所以if是不是真的需要。 – ollb 2010-07-27 22:09:49

相關問題