2013-03-25 107 views
2

假設我有一個STL向量,其元素是指向其他類的原始指針。很明顯,向量的析構函數不會釋放這些指針所擁有的內存。是否有可能實現一個釋放這個內存的自定義析構函數?STL容器中的自定義析構函數

+2

你需要的不僅僅是一個析構函數(以及三條規​​則的其餘部分);您還需要非常小心,不要因重新分配元素而丟失指針。有關血淋淋的細節,請參閱Boost指針容器的實現;在現代C++中,只需使用'vector '。 – 2013-03-25 12:24:52

+0

@MikeSeymour無論你做什麼,都不要在容器中使用'unique_ptr'。遲早,你肯定會做一些像'auto x = v [i];',從容器中有效地移除指向的對象。如果您必須使用'shared_ptr',但Boost指針容器是一個更好的解決方案,在極少數情況下容器應擁有這些對象。 – 2013-03-25 12:45:01

+0

@JamesKanze:你在想'auto_ptr',哪些(現在這些日子)​​你不應該使用任何東西?使用唯一的指針,'auto x = v [i]'不應該在沒有明確的'move'的情況下編譯。 – 2013-03-25 12:46:15

回答

4

在現代C++中,使用vector<unique_ptr<T>>,併爲您管理所有所有權問題。

如果C++ 11不可用,您可以使用shared_ptr(來自Boost或TR1)而不是unique_ptr,或者您可以使用Boost's pointer containers。 (不要試圖使用已棄用的auto_ptr,因爲這樣做太容易從容器中意外刪除指針了。假設第一條評論指的是這個,但將它與更安全的unique_ptr混淆。)

如果由於某種原因,你不能使用這些,或者如果你真的想自己做的工作,你需要與包裹載體的一類:

  • 刪除的每個存儲的指針析構函數;
  • 複製構造函數和複製賦值運算符,或者被刪除,或者執行「深度」複製;否則,存在兩個向量認爲他們擁有相同對象的危險;
  • 訪問器以這種方式讀取和修改元素,使得您不能覆蓋存儲的指針而不刪除其對象。
+0

使用'unique_ptr'確實是個問題。它在容器中不能很好地工作,因爲'auto x = v [i];'或'auto x = * iter;'會在容器中給你一個無效的'unique_ptr'。 – 2013-03-25 12:47:47

+4

@JamesKanze:不會的,因爲那不會編譯。 'auto x = move(v [i])'會將'unique_ptr'移出容器;但大概這就是你明確使用'move'的意圖。 – 2013-03-25 12:49:06

+0

@JamesKanze:除了在玩具程序中,我還沒有真正使用C++ 11的特性,但我的理解是'std :: unique_ptr'是爲了解決這個特殊問題而設計的。是什麼讓這個糟糕的(甚至是最糟糕的)解決方案? – 2013-03-25 13:16:12

0

您需要通過在刪除矢量進行迭代,並調用每個元素的析構函數裏面

或者我想最好的辦法是,而不是保存A *,保存shared_ptr<A>然後沒人的時候不再指向A,它將被破壞

+0

一個小警告:std :: vector沒有虛擬析構函數。 – 2013-03-25 12:26:02

+0

嗯,以爲這是因爲某種原因,謝謝編輯 – Alon 2013-03-25 12:26:55

3

不可以。您應該在破壞矢量之前手動清除元素。像

std::for_each(v.begin(), v.end(), [](const T* p) { delete p; }); 

,或者您可以使用類似boost::ptr_vector(或某些smart_pointers)的東西,即處理這種情況。

+0

如果你有C++ 11,使用'std :: unique_ptr'比使用lambda進行清理手動更清潔。 – 2013-03-25 12:36:33

+0

@DavidRodríguez-dribeas當然。 – ForEveR 2013-03-25 12:37:26

+0

@DavidRodríguez-dribeas使用'unique_ptr'是我能想到的最糟糕的解決方案之一。 – 2013-03-25 12:45:33