2017-02-12 59 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对象并代表它删除内存。

正如@詹姆斯在上面评论的那样,可能值得使用智能指针并让编译器和库为您完成工作。