以下代码实现了一个简单的哈希函数。我已经使用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;
}
答案 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
当你在容器中间捣乱时会做更多的复制。但它通过非常缓存友好来弥补这一点。