【问题标题】:Actively calling a destructor主动调用析构函数
【发布时间】:2013-06-01 19:07:11
【问题描述】:

在这篇文章中:

C++ Pointer: changing the contents without changing the address?

用户 Eric Postpischil 提出了一个答案,他主动调用了类的析构函数。 合法吗?它被认为是好的编程吗?

我问的原因是,在我的一堂课上,我的老师说这是禁止的,我们永远不应该这样做,他错了吗?

帖子上的问题和答案本身,虽然有趣与我的问题并不真正相关。

【问题讨论】:

  • 绝对不是禁止的。不过,新的展示位置几乎是您唯一想要的。
  • 我不知道这是否被禁止,但它是一种高级技术,可能只适用于非常特殊的情况。感谢您链接到该问题。我不知道placement-new。
  • 它是每个分配器的核心部分。标准中甚至有一个关于伪析构函数的专用部分,只是为了方便手动调用析构函数。
  • 我只能想到 1 次我这样做(在嵌入式平台上放置新相关) - 结果证明这是我的问题的错误解决方案。你的老师会给你一个普遍正确的答案,以免让你感到困惑或引诱你打开潘多拉的盒子。

标签: c++ destructor


【解决方案1】:

好吧,就像动态对象的创建过程可以“拆解”成两个阶段:原始内存分配和实际初始化(例如通过placement-new调用构造函数)一样,销毁动态对象的过程也可以是“反汇编”成两个阶段:实际的反初始化(析构函数调用)和原始内存释放。 (如您所见,这两个进程是彼此的镜像。)

这在您想要使用自己的原始内存分配/释放机制的情况下非常有用。当然,在很多情况下,您可以通过重载operator new/delete 来达到预期的效果,但在某些情况下它不够灵活,您可能更愿意显式执行上述步骤。

因此,这里有一个示例,说明直接析构函数调用何时是一项有用的功能。还有很多其他的。是的,这是完全合法的。

当您的班主任说您永远不应该这样做时,他/她可能的意思是您现在应该在当前课程范围内避免这样做。随着你学习的进步,你会明白许多“你永远不应该这样做”的技巧实际上是属于“如果你知道自己在做什么,就去做”类别的非常有用的技巧。当然,你不应该滥用这种技术,因为它确实是一种低级技术。

附:这种语法正式称为 pseudo-destructor call,因为它允许你“调用”不存在的析构函数

typedef int INT;

INT i;
i.~INT(); // <- legal code, pseudo-destructor call, no op

以上是合法的 C++ 代码,尽管 INT 不是类类型,因此没有析构函数。 (只是不要尝试这样做 i.~int() - 这是非法的。别名类型名必须用于非类类型。)

【讨论】:

  • 感谢您的回答,这让我真正理解了这次通话的目的。
【解决方案2】:

C++ 析构函数当然不是非法的,也不是被禁止的或不好的(当然,除非你做错了)。所以是的,严格来说,你的老师错了(尽管他可能只是想表达其他观点)。

最常见的例子是使用动态内存分配的类。简单地说,当在堆栈上为自己分配内存的类上调用析构函数时,该内存不会被释放。这意味着堆栈上有保留的内存,但没有被任何人引用,这意味着您无法访问它。换句话说,您有内存泄漏。但是,如果您正确创建析构函数并手动释放内存,则可以避免上述内存泄漏。

【讨论】:

    猜你喜欢
    • 2021-04-24
    • 2015-02-21
    • 2011-04-16
    • 2014-01-15
    • 2015-10-07
    • 1970-01-01
    • 2012-03-18
    相关资源
    最近更新 更多