在c ++中正确使用delete

时间:2017-02-12 00:35:01

标签: c++ new-operator delete-operator

首先,我很抱歉这个问题。我查看了与C ++中deletenew相关的大多数主要答案,但我仍然无法在此处纠正我的问题。 这里我有3个课程如下:

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作为delete table[i].pointer时,我也得到错误[core dumped]。那么在这些情况下我应该如何使用delete。在某些函数中使用了类实例(带有new)的用例的情况,例如:在C级上面的Split功能中或者我应该在这里改变整体风格吗?

2 个答案:

答案 0 :(得分:1)

TrieNode实例拥有其pointer类型bucket的实例,因此它负责通过在析构函数中调用delete来释放它。首先,您需要添加以下内容:

~TrieNode()
{
    delete pointer;
}

(请注意,pointer可能不是变量的一个很好的名称,因为它表示其类型而不是其用法。请考虑data或其他内容。)

然后每当删除TrieNode时,它的桶指针也会被删除。您可以在delete上安全地致电nullptr,它将不会执行任何操作,因此无需测试是否设置了pointer

由于哈希表使用std::vector<TrieNode>的实例,因此向量将包含(并拥有)对象实例。因此删除实例,删除HashTable等都应该正确清理。

一个潜在的问题是,如果您创建TrieNode的实例,然后将其传递给HashTable。这将生成对象的浅表副本(因为您尚未定义复制构造函数),因此您将有两个对象指向堆上的同一个存储桶。销毁第一个实例时,将删除存储桶。但是当第二个实例被销毁时,它同样会尝试第二次删除存储桶,并导致崩溃。我怀疑这解释了你描述的崩溃问题。

通常,如果您的类动态分配内存,它应该有一个析构函数和一个复制构造函数,以便正确管理内存。尝试对称地创建新/删除工作,因此拥有内存(调用new)的东西也是delete。哈希表不应该“到达”trie对象并代表它删除内存。

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

答案 1 :(得分: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 
  }

使用指定的类成员作为类成员和函数参数具有完全相同名称的变量是不好的做法,您有几个选项(可以使用'_'前缀来成员变量或重命名参数)