【问题标题】:C++ Destructor - Explicit calls in an Inheritance contextC++ 析构函数 - 继承上下文中的显式调用
【发布时间】:2023-04-03 12:29:01
【问题描述】:

我不确定我的问题有多大的针对性,但就是这样。

我知道只有在堆上分配内存时才应该显式调用析构函数。

假设我们有两个类:Animal 和 Dog,它是 Animal 的子类。

    Animal a* = new Dog();
    //-------Do something here-----//
    a -> ~Animal();

再次,假设 Animal 包含几个动态分配的字段,而 Dog 类添加了几个动态分配的字段。

由于 Dog 的字段较多,调用 Animal 的析构函数会导致内存泄漏。这只是糟糕的编程风格还是我们可以找到解决方法?

我想我们需要将指针转换为 Dog 类型,然后调用析构函数,但我找不到任何关于如何正确执行此操作的参考。

【问题讨论】:

  • 你描述的是原因,为什么任何应该被子类化的类都应该有一个虚拟析构函数。

标签: c++ memory destructor


【解决方案1】:

由于Dog的字段较多,调用Animal的析构函数会导致内存泄漏。

如果Animal 的析构函数是virtual,则不会发生这种情况。

此外,您无需致电~Animal()。一个例外是如果您正在编写自己的分配器。通常你会打电话给delete a

【讨论】:

  • 出于某种原因,我假设由于不允许使用虚拟构造函数,因此也不允许使用析构函数。我显然错了。
  • 来自Java背景,对我来说还是有点奇怪。分配器是指类似于 malloc 的自定义技术?
  • 是的——几乎没有人需要编写自己的分配器。您必须使用称为展示位置new 的特殊声明。
【解决方案2】:

我知道只有在堆上分配内存时才应该显式调用析构函数。

不,不,不,不,不,不。除非在非常特殊的情况下(我所知道的两个放置 new 和 unions),否则你永远不会显式调用析构函数。

你需要做的是在你的指针上调用delete。正如 rlbond 已经说过的,只要基类的析构函数是虚拟的,通过基指针删除就可以了。

【讨论】:

  • 你能给我一个具体的例子,我们应该明确地调用析构函数吗? - 已编辑:您的编辑回答了我的问题。
  • @SlowTrout 如果 (a) 您使用 placement new 在单独管理的存储中构造对象,您必须显式调用析构函数,或者(b) 该对象是您正在销毁的联合的当前活动成员。
  • 第二种情况非常合理。我需要进一步研究第一个案例。非常感谢您的回答。所以作为我理解的总结:我只需要确保我声明了虚拟的析构函数并正确设置了它的行为,并且'delete'将处理后续调用?
  • @SlowTrout I need to further research the first case 希望这并不意味着你会使用它(或者更好地说,滥用它)。除了在非常特殊的情况下,几乎没有理由使用placement-new。
  • 知道某事不会伤害你,但是是的,你是完全正确的。我做了一些关于它的阅读,它应该用于非常小的应用程序子集。
猜你喜欢
  • 2011-04-04
  • 1970-01-01
  • 2012-04-28
  • 2021-04-13
  • 2017-07-09
  • 2018-10-10
  • 2011-12-31
  • 2011-10-14
  • 2015-10-05
相关资源
最近更新 更多