2009-10-19 243 views
14

我遇到很多次代碼,其中在構造函數和析構函數中調用std :: vector類成員的std :: vector :: clear()。std :: vector :: clear()在構造函數和析構函數中

我不明白爲什麼它的需要:

  1. 構造 - STD型的類成員:: vector的默認是空的,所以沒有必要要求明確()。
  2. 析構函數 - 類型std :: vector的類成員將作爲包含它的對象的標準銷燬的一部分被銷燬。作爲矢量銷燬的一部分,所有值對象包含在其中將被銷燬(如果堆分配了指向內存的指針,則應該將它們手動刪除),因此再次不需要調用clear()。

我錯過了什麼嗎?

回答

16

從事物的聲音來看,編寫代碼的人就是那些錯過了某些東西的人。在ctor或者dtor中調用clear()將唯一有意義的時間是其他代碼的中間值。例如,ctor可能讀入一些數據,處理它,然後讀入更多數據。在這種情況下,讀取數據時使用單個容器可能會更快,並且每次都清除它,而不是每次迭代創建一個新容器。

5

不,你說得對。除非是在構造函數中的一些額外的業務(或基類的構造函數)是需要的,但機會是非常低的...

後來編輯

在析構函數的情況下,一個的我看到的最常見的錯誤是有些人認爲清除方法也會調用指針(向量)向量的刪除,當然,情況並非如此

22

不,您不會錯過任何東西。我懷疑這是(無害的)巫術編程,有點像在釋放它之後將指針設置爲null,或者在GUI代碼中隨機調用repaint/revalidate。程序員記得它過去幫助過某種錯誤,現在不必要地增加它「以防萬一」。誰知道,也許會有幫助。巫毒。

+2

不錯的術語,'巫術編程':) – xtofl 2009-10-19 20:51:49

+7

設置一個指針爲null不是巫術,它對調試有很大的幫助。也可以防止你刪除同一個指針兩次,但沒有人會這樣做 - 對吧? – 2009-10-19 21:01:25

+12

如果有的話,你想知道你刪除了同一個指針兩次。最好是大聲地失敗(並且瞭解它)而不是意外地成功(掩蓋一個會回來咬你的bug) – 2009-10-19 21:04:17

7
  1. 這是COMPLETELY unnessecary以清除在構造函數中
  2. 這是unnessecary以清除在析構函數除非容器包含一個指向一個STL容器的內容STL容器的內容。如果已經使用創建了指針,則仍然需要先刪除。在那之後,清理容器仍然不會是非常祕密的。

考慮一下:

#define BOOST_TEST_MODULE StlContainers 
#define BOOST_LIB_DIAGNOSTIC 

#include <boost/test/unit_test.hpp> 
#include <boost/assign.hpp> 
#include <boost/assign/list_of.hpp> 
#include <boost/assign/std/vector.hpp> 

#include <vector> 

using namespace boost::assign; 
using namespace std; 

const vector<int> my_ints_vector = list_of(0)(1)(1)(2)(3)(5)(8)(13)(21)(34); 

struct ScopedStruct1 
{ 
     ScopedStruct1(const vector<int> & v) : m_v(v) {} 
     ~ScopedStruct1() {} 
    private : 
     vector<int> m_v; 
}; 

class A 
{ 
    public : 
     A(int i) : m_i(i) {} 
     ~A() {} 
    private : 
     int m_i; 
}; 

struct ScopedStruct2 
{ 
    ScopedStruct2() {} 
    ~ScopedStruct2() { for(vector<A*>::iterator it = m_v.begin(); it != m_v.end(); ++it) delete *it; } 

    vector<A*> m_v; 
}; 

struct ScopedStruct3 
{ 
    ScopedStruct3() {} 
    ~ScopedStruct3() { /* no deletion */ } 

    vector<A*> m_v; 
}; 

BOOST_AUTO_TEST_CASE(StlContainer_storing_something_simple) 
{ 
    ScopedStruct1 str(my_ints_vector); 
} 

BOOST_AUTO_TEST_CASE(StlContainer_storing_pointers_with_delete) 
{ 
    ScopedStruct2 str; 
    for(int i = 0; i < 10; i++) 
     str.m_v.push_back(new A(i)); 
} 

BOOST_AUTO_TEST_CASE(StlContainer_storing_pointers_without_delete) 
{ 
    ScopedStruct3 str; 
    for(int i = 0; i < 10; i++) 
     str.m_v.push_back(new A(i)); 
} 

使用升壓轉換器的unit_test框架我創建了3測試用例。 unit_test框架是greate,因爲它跟蹤內存泄漏。 你會注意到第一個和第二個測試用例不會產生內存泄漏,但是第三種情況的確是因爲矢量的內容沒有被刪除。

+0

帶示例代碼的唯一答案..很好! – nkint 2013-06-18 09:51:21

-4

當然,人們已經調用clear()或調整(0)或同等的發言權(STD :: _ Destroy_range(...)在析構函數重新分配前

重分配是通過分配器進行: :取消分配不運行任何析構函數它只是釋放內存

明確的()相當於調整(0)運行在第一大小)的事情在分配的緩衝區析構函數(

NOT。只是分配了指針,文件句柄,持有mutexes,該對象持有的所有其他可回收資源。必須運行析構函數。在實例化之前,模板不知道析構函數是微不足道的。如果析構函數微不足道,那麼它在實例化後得到優化

+1

不,當矢量超出範圍時絕對會調用析構函數。不調用析構函數是沒有意義的。我建議你仔細檢查你的實施。您可以通過運行這樣的測試: 的#include 的#include 結構測試{〜測試(){性病::法院<< 「再見,世界\ n」; }}; int main(){std :: cout <<「Creating \ n」; std :: vector t(1); std :: cout <<「Created \ n」; } – janm 2009-10-20 00:47:17

+5

絕對不正確。 – 2009-10-20 00:51:35

+0

我在〜vector()中討論了一個明確的調用,而不是討論用戶定義的類的向量成員實例變量的明確調用 - 我的誤讀。 – pgast 2009-10-23 07:06:31

1

我能想到的唯一情況是它的用處在於銷燬的順序和析構函數想要確保向量中的對象被銷燬在別的之前。

當然,最好是結構化的代碼不要求;然而,這是一個可以想象的理由。

1

儘管到目前爲止所說的至少有一種情況,當在析構函數中顯式調用clear可能是必要的。

想象一下,當被銷燬的對象有多個成員子對象時,需要某種特定的銷燬順序,即子對象以某種方式相互依賴,並且其不正確的銷燬順序會導致不良結果。正如您可能知道的那樣,成員子對象銷燬的順序(以及成員初始化)由成員在類定義中聲明的順序決定。因此,一種實現正確銷燬順序的方法是相應地安排成員聲明。但是,首先,這不是一個非常好的解決方案。其次,破壞的期望順序可能取決於某些運行時間條件。第三,所需的破壞順序可能與想要的初始化順序相矛盾。這一切都意味着通過重新安排聲明來指揮正確的銷燬順序是不可能的(或明智的)。

在這種情況下,合理的方法可能是通過調用clean等方法手動清除一些關鍵成員子對象,直到銷燬順序依賴關係「消失」。我猜想,也許你看到的代碼試圖通過在戰略上選擇的vector子對象上調用clean來解決訂購問題。

至於在構造函數中調用clean ......我不知道爲什麼有人會這樣做。

+0

顯然你生活在太重新的話:)每次我檢查代碼時,它試圖在構造函數/析構函數中實現「乾淨」。關於你所描述的情況,我幾乎不可能想到它。最好應該做的,以避免它,如果不可能應該很好地評論 – dimba 2009-10-20 04:00:47

+0

我可能是錯的,但是當stl對象在範圍的末尾死亡 - 例如。它調用內部對象的析構函數。如果該對象也是一個stl容器,它也應該自動清除它自己。由「新」發起的指針會出現異常情況 - 像往常一樣 – Maciek 2009-10-20 23:42:33

+1

@Maciek:沒有人會爲此爭論。我要說的是,在某些情況下,自動*清除的順序可能是不可接受的。在自動清理開始之前,您可能需要自行定製預清理。 – AnT 2009-10-21 00:02:43

相關問題