我是否必须使用删除以避免内存泄漏?我用new来分配结构实例

时间:2014-07-23 15:16:51

标签: c++ memory-management memory-leaks destructor

以下代码实现了一个简单的哈希函数。我已经使用new运算符分配了struct实例。

程序结束时我是否使用delete运算符?

如果是这样,我该怎么办? [结构的每个实例的一个delete语句?或者有更简单的方法吗? ]

#include <iostream>
#define SIZE 10

using namespace std;

typedef struct myhashtag
{
   int data;
   struct myhashtag * next;
} myhash;
void printhash(myhash array[])
{
// print fn
}

void hash(int data, myhash array[])
{
   int h = data % SIZE;
   myhash * newhash = new myhash;
   newhash->data = data;
   newhash->next = NULL;

   if(array[h].next == NULL)  //first insert
   {
      array[h].next = newhash;
      return;
   }
   myhash * iter = array[h].next;
   while(iter->next != NULL)
   {
      iter = iter->next;
   }
   iter->next = newhash;
   return;
}


int main()
{
   myhash array[SIZE];int i;
   for(i=0; i<SIZE; i++)
   {
      array[i].data = 0;
      array[i].next = NULL;
   }

   while(1)
   {
      cout << "\nSo, what would you like to enter? : ";
      cin >> i;
      hash(i, array);
      printhash(array);
   }

// the deletes go here 

   return 0;
}

3 个答案:

答案 0 :(得分:3)

通常,对于每个使用new的分配,您确实需要对数组执行一次删除(或删除[]。

如果您使用的是Linux,那么valgrind可以帮助检测内存泄漏。

最新版本的C ++以及Boost库提供了各种智能指针,当对象不再被引用时,它们基本上会自动释放内存。

在您选择的C ++书中查找std :: unique_ptr。

答案 1 :(得分:1)

是的,您应该始终删除您分配的任何动态内存。

您可以实现一个简单的RAII容器来处理内存清理。只需创建一个类来充当句柄,在其构造函数中记忆内存。在析构函数中删除它并提供某种访问机制。这样,任何内存都会在handleis声明的范围的末尾自动清理。

答案 2 :(得分:1)

C ++确实需要您管理对象的生命周期。它并不像许多Java或C#书籍可能让您相信的那么难。但是,是的,如果不使用garbage collector,您需要确保delete被恰当地调用。

我可以通过两种方式为您发布的代码执行此操作。正如其他人所建议的那样,第一个是使用std::unique_ptr

第二个是给你的struct一个析构函数。我不太清楚为什么你使用经典的C typedef struct ...成语(你在C中这样做,所以你不必经常使用struct关键字,但你不必在C ++中经常使用struct关键字)。我会将其保留在后面的代码中,但我想将其标记为非语义:

typedef struct myhashtag
{
   int data;
   struct myhashtag * next;

   ~myhashtag()
   {
      if (next) {
         delete next;
      }
   }
} myhash;

(您仍然需要确保delete您放置“删除此处”的评论的头节点。)

但是,这假设next在列表末尾正确分配给NULL。您发布的代码就是这样做的,但它只是按惯例强制执行的。稍微习惯的方法是:

struct hash_node {
   int data;
   hash_node* next;

   hash_node(int d, n = NULL) : data(d), next(n) { }

   ~hash_node()
   {
      if (next) {
         delete next;
      }
   }
};

void hash(int data, hash_node* array)
{
   int h = data % SIZE;
   hash_node* newhash = new hash_node(data);

   if(array[h].next == NULL)  //first insert
   {
      array[h].next = newhash;
      return;
   }
   hash_node* iter = array[h].next;
   while(iter->next != NULL)
   {
      iter = iter->next;
   }
   iter->next = newhash;
   return;
}

更惯用的方法是:

#include <list>
#include <iostream>
using namespace std'

int main()
{
    list<int> list_that_the_code_was_calling_a_hash;
    while(1) {
        cout << "\nSo, what would you like to enter? : ";
        cin >> i;
        list_that_the_code_was_calling_a_hash.push_back(i);
        if (list_that_the_code_was_calling_a_hash.size() > 10) {
            list_that_the_code_was_calling_a_hash.pop_front();
        }
        printhash(list_that_the_code_was_calling_a_hash);
    }
    return 0;
}

许多人会建议使用std::vector,因为std::list只是与您的CPU缓存无法很好地交互。是的,std::vector当你在容器中间捣乱时会做更多的复制。但它通过非常缓存友好来弥补这一点。