2010-10-31 46 views
18

我有一個向量,我填充指向對象的指針。我想學習好的內存管理,並有幾個一般性的問題:在刪除指向動態分配對象的向量的元素之前,我需要做些什麼?

  1. 這是真的,當我與向量做,我必須遍歷它,並呼籲每個指針刪除?
  2. 爲什麼我不必調用vector或其他聲明的變量而不聲明新聲明,但是必須在指針上調用delete?
  3. 如果向量是在返回的函數中聲明的(導致向量超出範圍),C++是否會爲我釋放指針的內存?

回答

21
  1. 載體使用的是照顧內存管理你的模板的內存分配來實現,所以他們有些特別。但作爲一般的經驗法則,您不必針對未使用new關鍵字聲明的變量調用delete,因爲堆棧和堆分配存在差異。如果東西在堆上分配,它必須被刪除(釋放)以防止內存泄漏。
  2. 不可以。在迭代所有元素時,您必須明確地調用delete myVec[index]

例:

for(int i = 0; i < myVec.size(); ++i) 
    delete myVec[i]; 

隨着中說,如果你在一個向量保存指針的規劃,我強烈建議使用boost::ptr_vector自動採取刪除的照顧。

+1

3:C++當然會釋放指針使用的內存,因爲它們被分配在堆棧上。但是這些指針指向的對象最有可能分配在堆上,因此需要刪除。當然,向量中的指針可能指向堆棧分配的對象,這些對象可能不會被刪除。一般來說,你絕不應該存儲非const指針來將矢量中的已分配對象堆棧。 – smerlin 2010-10-31 01:35:14

+1

謝謝!這很清楚! – 2010-10-31 03:38:23

2

如果您有權訪問C++ 0x,也可以使用std :: unique_ptr。它取代了不能在容器中使用的不推薦使用的std :: auto_ptr。

2

您分配的所有東西都需要new您稍後需要delete。對象,你不明確分配new不應該delete

如果您不想手動管理對象,但希望矢量「擁有」它們,那麼按值存儲對象可能會更好,而不是存儲指向它們的指針。因此,您可以使用std::vector<SomeClass>而不是std::vector<SomeClass*>

10

是不是真的,當我完成載體,我必須通過它循環,並調用刪除每個指針?

那麼,你不必用手圈,你也可以使用一個算法:

#include <vector> 
#include <algorithm> 
#include <memory> 

int main() 
{ 
    std::vector<Base*> vec; 
    vec.push_back(new Derived()); 
    vec.push_back(new Derived()); 
    vec.push_back(new Derived()); 

    // ... 

    std::for_each(vec.begin(), vec.end(), std::default_delete<Base>()); 
} 

如果你沒有的C++ 0x編譯器,你可以使用boost:

#include <boost/lambda/lambda.hpp> 
#include <boost/lambda/construct.hpp> 

std::for_each(vec.begin(), vec.end(), boost::lambda::delete_ptr()); 

或者你可以寫自己的仿函數:

struct delete_ptr 
{ 
    template <class T> 
    void operator()(T* p) 
    { 
     delete p; 
    } 
}; 

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

作爲替代boost::ptr_vector由大衛Titarenco提到的,你可以很容易地修改的std ::矢量,自動釋放內存包含在刪除指針:

template<class T> 
class Group : public std::vector<T> 
{ 
public: 
    virtual ~Group() {}; 
}; 

template<class T> 
class Group<T *> : public std::vector<T *> 
{ 
public: 
    virtual ~Group() 
    { 
     std::vector<T *>::reverse_iterator it; 
     for (it = this->rbegin(); it != this->rend(); ++it) 
      delete *it; 
    } 
}; 

通過的std ::矢量提供的所有功能,是繼承,所以你會增加項目以同樣的方式:

Group<Foo *> *bar = new Group<Foo *>(); 
bar->push_back(new Foo()); 
bar->push_back(new DerivedFoo()); 

// Deleting the Group will free all memory allocated by contained pointers 
delete bar; 
相關問題