2017-02-12 54 views
1

首先我對這個問題感到抱歉。我已經在C++中查看了與deletenew相關的大多數主要答案,但我仍然無法在這裏糾正我的問題。 這裏我有3類,如下所示:在C++中正確使用刪除

class bucket 
{ 
    // Some stl container here where data would be inserted 
    // Some methods and fields here 
    // This class has no new keyword 
}; 

class TrieNode 
{ 
    public: 
    bucket *pointer; 
    TrieNode() //Constructor for this class 
    { 
     pointer = NULL; 
    }; 
    TrieNode(int local) //Parametrized Constructor for this class 
    { 
     pointer = new bucket(local); //Here is the new keyword 
    } 
}; 

class Hashtable 
{ 
    private: 
    int globalDepth; 
    std::vector<TrieNode> table; //Vector of other class 

    void Split(int index) 
    { 
    // Here I am creating instances of other class(TrieNode) which has pointer 
     TrieNode first(capacity); 
     TrieNode second(capacity); 
    // Then after some processing I have to do this 
     table[index] = first; //Assignment which will be using new keyword in it's class i.e. first 
     table[mirrorIndex] = second; //again assignment 
    } 
public: 
    Hashtable(int globalDepth) //Constructor for this class 
    { 
     std::cout<<"Table is being created...\n"; 
     this->globalDepth = globalDepth; 
     table.resize(pow(2,globalDepth),TrieNode()); //vector of class here 
    } 
}; 

int main(int argc, char const *argv[]) 
{ 
    bool input = true; 
    Hashtable mytable(1); //Instance of Third class 
} 

現在我的問題是,當我在TrieNode類使用析構函數與delete pointer它讓我儘快分段錯誤,我嘗試在C級的載體插入一些因爲析構函數創建後自動調用,它刪除了向量吧?],當我在C類的析構函數爲delete table[i].pointer使用delete然後我得到的錯誤太[核心轉儲。那麼在這些情況下我應該如何使用delete。我在一些函數中使用了一個類實例(帶有new)的例子,例如在C類的Split函數中還是應該改變整體風格?

+1

學習使用gdb並閱讀std :: unique_ptr和複製構造函數(他們實際複製的內容) – James

+0

@James Sure。謝謝! –

回答

0
class TrieNode 
{ 
    public: 
    bucket *pointer; 
    TrieNode() //Constructor for this class 
    { 
     pointer = NULL; 
    } 
    ~TrieNode() //destructor for this class 
    { 
     pointer = NULL; 
delete pointer; 
    } 
    TrieNode(int local) //Parametrized Constructor for this class 
    { 
     pointer = new bucket(local); //Here is the new keyword 
    } 
}; 

你在哪兒定義的能力? 有一個';'你的構造函數定義之後,我刪除了。 你的類的析構函數只需要用new刪除堆中分配的對象,編譯器會負責銷燬所有局部變量,你只關心分配的是什麼。

Hashtable(int nGlobalDepth) //Constructor for this class 
    { 
     std::cout<<"Table is being created...\n"; 
     this->globalDepth = nGlobalDepth; 
     table.resize(pow(2,globalDepth),TrieNode()); //vector of class here 
    } 

使用指定的類成員是不好的做法,你有幾個選項(可以用「_」前綴類成員變量有完全相同的名稱都被作爲一個類的成員,並作爲函數的參數變量或重命名參數)

+0

我沒有顯示所有類和方法的完整代碼。 'capacity'是在方法中定義的一個'int'。我會檢查這段代碼,並在我完成後立即回覆。感謝你的方式和一個問題,你爲什麼要做'指針NULL',然後'刪除'它。它的目的是什麼? –

+0

@SunilKumar在刪除之前刪除指針是錯誤的 – James

+0

在矢量中使用您的建議將會中斷,因爲TrieNode不符合三的規則 –

1

一個TrieNode實例擁有其bucketpointer實例,所以它負責在析構函數調用delete釋放它。所以,首先你需要添加類似:

~TrieNode() 
{ 
    delete pointer; 
} 

(注意pointer可能不是一個變量一個偉大的名字,因爲它是表示它的類型,而不是它的使用考慮data什麼的。)

然後每當TrieNode被刪除,它的桶指針也會被刪除。您可以在nullptr上安全地撥打delete,它不會執行任何操作,因此無需測試是否設置了pointer

由於哈希表使用的std::vector<TrieNode>情況下,所述載體將含有(和自己)的對象實例。因此刪除一個實例,刪除HashTable等應該都清理正確。

一個潛在的問題是如果您創建一個TrieNode的實例,然後將它傳遞給HashTable。這將創建對象的淺表副本(因爲您尚未定義複製構造函數),因此您將有兩個對象指向堆上的同一個存儲桶。當第一個實例被銷燬時,該桶將被刪除。但是當第二個實例被銷燬時,它同樣會嘗試第二次刪除這個桶,並導致崩潰。我懷疑這解釋了你描述的崩潰問題。

在一般情況下,如果你的類動態分配內存,它應該有一個析構函數和拷貝構造函數,使內存能夠正確地管理。嘗試使對稱的新/刪除工作,所以擁有內存的東西(調用new)也delete它。散列表不應該「到達」trie對象並代表它刪除內存。

正如@詹姆斯在上面評論的那樣,可能值得使用智能指針並讓編譯器和庫爲您完成工作。