2011-03-25 83 views
1

我正在實施標準模板樹結構,並遇到小問題。刪除指針的方法:delete/delete []/free?

想法,每個節點將持有指向一些數據的指針。後來爲了正確地刪除元素,我需要知道它是單個指針還是指向數組的指針。

裏面我tree->ReleaseMemory()方法我有這樣的代碼:

if (node->_data != NULL) { 

     switch (_destructionMethod){ 

     case tree_delete: 
      delete node->_data; break; 
     case tree_deleteList: 
      delete [] node->_data; break; 
     case tree_free: 
      free(node->_data); break; 

    } 


} 

其中_destructionMethod已節點的初始化過程中設置。 有沒有什麼辦法可以選擇正確的析構函數,而無需在初始化過程中爲其定義特殊變量?

謝謝!

+0

我想這是一個很好的時間讓我弄清楚如何使用智能指針,可選地我會回來對象包裝。謝謝 – kirbo 2011-03-25 23:25:30

回答

1

不要這樣做。使用智能指針,如C++ 0x或Boost中的shared_ptr,或者如果不是C++中的auto_ptr選項。如果您可以有多個對象,請考慮使用std::vector

手動資源管理很混亂,很難正確對待。

+1

雖然這可能是可能的,但根據情況使用原始指針/數據可能仍然有效。但如果是這樣 - 我不認爲應該實施一個發佈,除非你從一開始就處理這個分配。 – stefan 2011-03-25 23:11:54

+0

並注意在C++中存在'boost :: checked_array_deleter'和'std :: default_delete '0x – 2011-03-25 23:25:19

+0

並避免在STL容器中使用std :: auto_ptr <>:http://stackoverflow.com/questions/111478/why-it-it-it-it-to-use-stdauto -ptr-with-stl-containers – rturrado 2011-03-26 00:28:27

4

首先基本的:當你與malloc分配內存

int *p = new int; 
int *a = new int[10]; 
//... 
delete p; 
delete []a; //note the difference! 

free用於:

int *p = (int*)malloc(sizeof(int) * 1); 
int *a = (int*)malloc(sizeof(int) * 10); 
//... 
free(p); 
free(a); //no difference! 

現在你當你new分配內存

delete使用問題:

有什麼辦法,我可以選擇正確的析構函數沒有初始化期間

考慮policy-based design爲它特殊的變量預先定義它。這意味着,編寫allocator將封裝分配和解除分配到一個類中,並在代碼中一致地使用它。

+3

我很確定提問者知道這一點,因爲他在初始化時設置了_destructionMethod。我寧願認爲這個問題正在尋求避免對這個存儲值的需要,它不會詢問要存儲哪個值。 – 2011-03-25 23:19:53

2

不,沒有可移植的方法來找出一個特定的指針最初來自哪個分配器。

2

沒有辦法查詢一個指針來找出它是如何分配的,但一個常見的習慣用法是讓分配的對象本身負責自己的銷燬。它看起來像你的對象類型不是所有類的類型,所以你需要包裝它們才能做到這一點。例如:

class destroyable_node 
{ 
    virtual void destroy() = 0; 
}; 

template <typename T> class object_node : public destroyable_node 
{ 
private: 
    T * value_; 

public: 
    // Presumes T is copy-constructable. 
    object_node(T value) : value_(new T(value)) {} 

    operator T&() {return value_;} 
    operator T const &() const {return value_;} 

    void destroy() {delete value_;} 
}; 

template<typename T> class array_node : public destroyable_node 
{ 
private: 
    T * value_; 

public: 
    array_node(T[] value) 
     : value_(new T[ sizeof(value)/sizeof(T) ]) 
    { 
     std::copy(value, value + sizeof(value)/sizeof(T), value_); 
    } 

    operator T*() {return value_;} 
    operator T const *() const {return value_;} 

    void destroy() {delete[] value_;} 
}; 

...等等。

0

也許一個更好的設計是實現一個抽象接口使用你的容器與三個具體的子類,知道他們拿着指針什麼樣的事情。你的容器只需在基類中調用destroy()方法,讓派生類擔心調用正確的析構函數。