关于C++中自定义对象的构造函数/析构函数和new/delete运算符

4
假设我有一个自己创建的链表。它有自己的析构函数,可以释放内存。这个链表没有重载new或delete。
现在,我正在尝试创建一个所述链表的数组(如果我理解正确的话,这是一种开放式哈希)。然后,在此开放式哈希类的构造函数中分配必要的内存。在构造函数内部调用的new运算符足以正确地为数组分配内存,对吗?我不确定,因为我没有为链表类重载new。
另外,假设我的链表数组被称为elements,我是否可以只写“delete[] elements”在析构函数中?那样会调用数组中每个元素的析构函数并正确释放内存吗?
最后,如果我的两个假设都是正确的(即,我不需要重载new和delete来使用它们与我的自定义类),那么重载这些运算符的意义是什么?

如果必须使用new,请使用shared_ptrunique_ptr。两者都是在c++11 STL <memory>中引入的。 共享指针将自动进行删除的簿记。注意:对于数组,由shared_ptr提供的默认删除器调用delete,而不是delete[],因此请使用lambda函数std::shared_ptr<int> p(new int[10], [](int* p) { delete[] p; });或者std::shared_ptr<int> p(new int[10], std::default_delete<int[]>());或者使用从unique_ptr提供的帮助程序,该程序调用delete[]std::unique_ptr<int,void(*)(int*)> p(new int[10], [](int* p) { delete[] p; }); - katta
3个回答

6
是的,你说得对。一个普通的
elements = new LinkedList[N];

足够分配它们。然后您可以访问它们。
elements[i]->push(....);

并在析构函数中使用您展示的方法删除它们:

delete[] elements;

编译器将记住分配的元素数量,并正确调用每个列表的析构函数。重载new和delete运算符的目的是提供自定义的内存分配策略。例如,您可以预先分配内存,然后从该池中取出,而不是每次都从操作系统重新分配内存。

但请注意,您还必须编写复制构造函数和复制分配运算符。因为如果有人复制您的哈希映射,链接列表也必须被复制,而不仅仅是指针。或者您可以将复制构造函数和复制分配运算符设为私有并不定义它们,从而禁止复制您的哈希映射:

....
private:
    MyHashMap(MyHashMap const& rhs);
    MyHashMap & operator=(MyHashMap const& rhs);
....

一个小细节:大多数 new 的调用并不涉及操作系统。通常只有在堆需要获取更多虚拟内存页面时,操作系统才会介入。 - Scott Wisniewski

3
new 操作符有两个作用:分配内存和调用构造函数。 delete 操作符会调用析构函数,然后释放内存。
使用 new [] 创建的数组必须使用 delete[] 销毁。
通常情况下不需要重载 newdelete,除非出于性能原因。你可能有一种可预测的分配/销毁模式,使得某种分配策略非常合适(快速或低内存使用)。
你可以参考这个页面

1

你的所有假设都是正确的。

重载 new 和 delete 有很多用途,但并不经常使用。一个常见的原因是为了跟踪内存分配以便发现内存泄漏。很多编译时泄漏跟踪器都这样做,但随着像 valgrind 这样更好的外部应用程序的出现,它们已经有点过时了。你也可以做一些像使用池化内存这样的事情。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接