【问题标题】:About constructors/destructors and new/delete operators in C++ for custom objects关于 C++ 中自定义对象的构造函数/析构函数和 new/delete 运算符
【发布时间】:2023-03-27 01:44:01
【问题描述】:

假设我有一个我自己创建的链接列表。它有自己的析构函数,可以释放内存。此链接列表不会重载 new 或 delete。

现在,我正在尝试创建一个所述链接列表的数组(如果我理解正确,则为开放散列)。然后我在这个开放散列类的构造函数中分配必要的内存。在构造函数中调用的 new 运算符足以为数组正确分配内存,对吧?我不确定,因为我没有为 Linked List 类重载 new。

另外,假设我的链接列表数组被称为元素,我可以在析构函数中写“删除[]元素”吗?这会为数组中的每个元素调用析构函数并正确释放内存吗?

最后,如果我的两个假设都是正确的(即,我不必重载 new 和 delete 就可以在我的自定义类中使用它们),那么重载这些运算符有什么意义?

【问题讨论】:

  • 如果你必须使用新的使用shared_ptrunique_prt。两者都是在 c++11 STL 中引入的。共享指针将自动记录删除。注意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; });

标签: c++ constructor destructor new-operator


【解决方案1】:

是的,你是对的。一个普通的

elements = new LinkedList[N];

足以分配它们。然后你就可以访问它们了

elements[i]->push(....);

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

delete[] elements;

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

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

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

【讨论】:

  • 一个小问题:大多数调用 new 不涉及操作系统。通常,只有在堆需要获取更多虚拟内存页面时,操作系统才会参与其中。
【解决方案2】:

new 操作符做了两件事:分配内存和调用构造函数。

delete 操作符调用析构函数,然后释放内存。

使用 new [] 创建的数组必须使用 delete[] 销毁。

您通常不需要重载 newdelete,除非出于性能原因。您可能有一个可预测的分配/解除分配模式,这使得特定的分配策略非常适合(快速或低内存使用)。

您不妨看看this page

【讨论】:

    【解决方案3】:

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

    重载 new 和 delete 有很多用途,但并不经常这样做。一个常见的原因是跟踪内存分配以发现内存泄漏。很多编译时泄漏跟踪器都这样做,但是随着 valgrind 等更好的外部应用程序已经过时了。您还可以执行诸如使用池化内存之类的操作。

    【讨论】:

      猜你喜欢
      • 2011-06-11
      • 2017-12-22
      • 2014-01-22
      • 1970-01-01
      • 2017-06-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多