【问题标题】:Destructor for a template container模板容器的析构函数
【发布时间】:2018-08-22 17:29:24
【问题描述】:

我正在 C++ 中构建一个类似 Java 的 ArrayList 类,只是为了练习(是的,我知道std::vector 和其他很好的替代方案存在)。

我了解new 关键字与delete 关键字配对,malloc, calloc, reallocfree 配对。

所以,假设我有一个类ArrayList,其中包含指向某个泛型类型T 的指针。换句话说,我的ArrayList 中的底层数组是这样的

T* array 其中T 是一些template <typename T>

我正在为ArrayList 定义我的析构函数,我有几个问题..

  1. 析构函数应该负责释放存储在ArrayList 中的所有内存。但我不知道它持有的T*s 是使用new 还是malloc-type 创建的,那么我该如何释放它们呢?我觉得遇到这个问题是一种反模式的迹象,所以任何建议都将不胜感激!

  2. ArrayList 本身可以通过两种方式实例化

在堆栈上...

ArrayList arr;

或在堆上...

ArrayList arr = new ArrayList();

如果它是在堆栈上初始化的,我不必担心管理arr 的内存,但我可以假设它的析构函数会在arr 本身以某种方式被释放之前被调用吗?

如果它是在堆上初始化的,调用delete arr会调用它的析构函数并且释放arr本身吗?

谢谢!

【问题讨论】:

  • 1) 你为什么写ArrayList,如果std::vector 就是这样? 2) 通常,容器类管理自己的内存,因此您知道array 的内存是如何分配的。提示:您应该尽可能避免使用malloc,因为它不会调用构造函数,而new 会调用。 3)通常,类不应该关心它们是如何分配的。它对类内部结构没有任何改变。
  • malloc/free 不构造或破坏对象,并且不适用于大多数类类型。 new/delete 会。
  • 如原帖所述,我这样做是为了练习。我不希望malloc 调用构造函数,我假设ArrayList 将存储指向预构造对象/基元的指针。
  • @Carpetfizz 但我不知道它持有的 T 是使用新类型还是 malloc 类型创建的,那么我该如何释放它们呢? -- 你不知道,除非客户告诉你如何解除分配。客户端可能刚刚存储了一个非动态创建对象的地址,或者一个使用操作系统 API 调用创建的对象(即 Windows 中的 LocalAlloc)。
  • @Carpetfizz -- 你可以做智能指针类std::shared_ptrstd::unique_ptr 所做的事情。假设“删除器”是delete,并让您的班级拥有客户端提供的自定义删除器。 See here

标签: c++ arrays


【解决方案1】:

解构器应该负责释放存储在ArrayList 中的所有内存。但我不知道它所持有的T*s 是使用新类型还是malloc-type 创建的,那么我该如何释放它们呢?我觉得遇到这个问题是一种反模式的迹象,所以任何建议都将不胜感激!

你不应该接受任何T*s。您是正确的,您无法确定应如何释放此类指针。您应该自己处理分配(就像std::vector 所做的那样),在这种情况下您就不会再遇到这个问题了。

如果它是在堆栈上初始化的,我不必担心管理arr 的内存,但我可以假设它的解构器将在arr 本身以某种方式被释放之前被调用吗?

是的。当局部变量超出范围时,对象(如果有)将被销毁。这涉及调用它的析构函数(如果有的话)。

如果它是在堆上初始化的,调用delete arr会调用它的解构函数并释放arr本身吗?

是的。 delete arr 调用 arr 的析构函数(如果有的话)并释放保留的内存。

【讨论】:

  • 感谢您解惑!我对你的第一点有疑问。你自己分配分配是什么意思?用户按照自己的意愿构建对象,并将其交给ArrayList 进行存储。
  • @Carpetfizz 如果将对象提供给ArrayList,那么您需要通过将它们复制到ArrayList 中来存储它们。ArrayList 现在负责删除副本。
  • @Carpetfizz 这就是std::vector 的工作原理。然而,Java 有一个完全不同的机制,它基于每个对象都是引用(带有引用计数)并将引用存储在容器中。并使用垃圾收集代替显式销毁。
  • @Carpetfizz 如果你有一个std::vector<Foo>,那么向量将负责销毁其析构函数中的任何Foo 对象。如果您有一个std::vector<Foo*>,那么当该向量被销毁时,指向的Foo 对象将不会被销毁。
  • @Carpetfizz 最后评论(因为我认为你需要读一本书)。对象通过复制它们被放入std::vectorstd::vector 负责删除这些副本。原件发生的事情是调用者的责任。书单:stackoverflow.com/questions/388242/…
猜你喜欢
  • 1970-01-01
  • 2018-04-30
  • 2020-07-21
  • 2017-04-14
  • 2018-09-08
  • 1970-01-01
  • 2016-10-07
  • 2017-10-20
  • 2012-07-24
相关资源
最近更新 更多