2010-08-20 44 views
3

我在下面的矢量中存儲動態分配的類指針。與數組相比,釋放矢量的問題

 vector<Test *> v; 
    Test *t1 = new Test; 
    Test *t2 = new Test; 
    v.push_back(t1); 
    v.push_back(t2); 

現在,如果我有免費的測試對象,我必須通過整個向量和免費一個循環接一個,然後做一個明確的。

for(int i = 0; i<v.size(); i++) 
    { 
     delete v[i]; 
    } 
    v.clear(); 

是否有向量中的任何函數來釋放所有內部對象。該函數應該爲每個對象調用Test class destructor。 我知道Vector類的指針是本地對象的地址還是動態分配是困難的。 但是,每當開發者確信所有的動態分配,他都可以使用釋放函數(如果提供的話)。

雖然vector被視爲高級數組,但釋放數組中的對象比下面的要容易得多。

Test *a = new Test[2]; 
delete []a; 

是否有向量中的任何函數來釋放所有內部對象?

+0

我可以評論一下,在第一種情況下,寫'Test * a = ...'和delete [] a;'是更清楚的,類型是指向Test的指針(實際上是一個數組,但一般來說在我看來,把類型寫成一個單詞是更好的:'Class * someObject'),而在第二種情況下,你在'a'上使用運算符'delete []',而在'[' ] a',這幾乎不相同。 – rubenvb 2010-08-20 12:05:16

回答

4

你的例子根本不會做同樣的事情。

如果你想在矢量相當於該陣列碼:

Test *a = new Test[2]; 
delete []a; 

那簡直是

std::vector<Test> a(2); 

如果你有一個指針的向量,以動態分配的對象,你需要刪除每一個其中,如在你的例子:

for(int i = 0; i<v.size(); i++) 
{ 
    delete v[i]; 
} 

但同樣的事情是真實的陣列Y:

Test *t1 = new Test; 
Test *t2 = new Test; 
Test **a = new Test*[2]; 
a[0] = t1; 
a[1] = t2; 

有這樣的循環被刪除:

for(int i = 0; i<2; i++) 
{ 
    delete a[i]; 
} 
delete[] a; 

在第一種情況下,你必須存儲在某種類型的容器兩個對象。該容器可能是一個矢量,或者它可能是一個數組。

在這兩種情況下,因爲對象直接存儲在容器中,所以在容器被銷燬時會調用它們的析構函數。你不需要做任何破壞或刪除單個成員的操作,你只需要銷燬容器(使用堆棧分配的向量更簡單,你甚至不需要調用delete[]

但是如果你的容器存儲指向動態分配對象的指針,那麼你有責任在某個時候刪除這些對象。無論您的容器是數組還是矢量,情況都是如此。

+0

然後我想知道'''''''''''你的'a'數組有什麼作用? – rubenvb 2010-08-20 12:18:54

+0

@rubenvb:它刪除數組。但是如果數組存儲指針,它將不會刪除這些指針指向的內容。 – jalf 2010-08-20 12:19:51

+0

@jalf:啊哈,我現在明白了。不使用數組的另一個原因。 – rubenvb 2010-08-20 13:04:40

2

不,沒有辦法要求全部指針自動在其所有元素上調用delete

然而,還有其他的第三方容器,當它們從向量中移除時,或者向量被破壞時,會自動刪除指針,從而使這類事情更容易。例如,boost::ptr_vector and friends

2

簡短的回答是否定的。 C++不提供指針釋放函數的向量。

長的答案是雙重的:

  1. 使用智能指針,而忘記了free'ing(有shared_ptrunique_ptr C++ 0x中,這將有助於滿足你的需要)。或者,像Tyler建議的那樣使用Boost ptr_vector。

  2. 向容器中的每個項目(使用帶迭代器的模板)編寫一個簡單的通用算法到delete並不困難。

(警告:未經測試的代碼,沒有時間去檢查它)

template<class It> 
void delete_clear_ptr_cont(const It &beginIt, const It &endIt) 
{ 
    for(auto it = beginIt; it != endIt; ++it) 
    { 
     delete it; 
    } 
    erase(beginIt, endIt); 
} 
0

我問過同樣的問題,我建議使用Boost庫,你會發現偉大的祕訣 here或簡單地你可以理解如下智能指針:

而不是有一個向量的指針,你將有一個向量智能指針,至於每個新的,你會使它將刪除本身沒有你不必擔心。

1

不,vector不知道它可能用指針實例化。即使是這樣,在某些情況下,您並不擁有指針,也不希望刪除行爲。

在大多數情況下,我們只需使用智能指針向量,如shared_ptr。但是,有些時候shared_ptr不合適。對於這些情況,我們有這樣的在我們的工具箱中的仿函數:

#include <functional> 

template<typename T> 
struct PointerDelete : public std::unary_function<T*, T*> 
{ 
    T* operator()(T*& p) const 
    { 
     delete p; 
     return 0; 
    } 
}; 

然後,假設你有一個vector<Foo*>,你可以做兩種:

#include <algorithm> 

std::for_each(v.begin(), v.end(), PointerDelete<Foo>()); 
// or 
std::transform(v.begin(), v.end(), v.begin(), PointerDelete<Foo>()); 

如果你可以使用boost庫,有還有ptr_containers,它們是取指針的所有權的容器,並在容器銷燬時自動執行刪除。