C++的析构函数是否总是或只是有时调用数据成员的析构函数?

12
我正在尝试验证我对C++析构函数的理解。
我已经多次阅读到,如果我不自己编写析构函数,C++会提供一个默认的析构函数。但是,这是否意味着如果我编写了一个析构函数,编译器仍然会提供默认的清理堆栈分配的类字段的功能呢?
我的直觉是,无论如何,所有的类字段都会被销毁,无论我是否提供自己的析构函数。在这种情况下,原始语句中的"if"子句实际上有点误导性,更好的陈述方式可能是:
"无论您是否编写自己的析构函数,C++编译器始终会编写一个类似默认析构函数的序列来释放您的类的成员变量。然后,您可以根据需要定义自己的析构函数来指定额外的释放或其他任务。"
这样说对吗?
3个回答

26

当C++中的对象被清理时,语言将:

  • 首先调用类的析构函数,接着
  • 调用类所有字段的析构函数。

(假设没有继承; 如果有继承,则通过递归遵循相同的过程来销毁基类)。因此,您编写的析构器代码只是自定义清理代码,希望在个别数据成员的正常清理代码之外执行。您不会以某种方式丢失正常调用那些对象的析构函数。

希望这能帮到您!


谢谢,这正是我在寻找的答案。 - Magnus
我希望所有的回答都能像这样清晰地表达。非常感谢。 - Tovi7

2
是的 - 任何包含在您的对象中的对象都将作为销毁您的对象的一部分而被销毁,即使/尽管您的析构函数未执行任何操作来销毁它们。
实际上,您的析构函数通常不会对包含在对象中的对象执行任何销毁操作;它通常的作用是销毁通过对象中的某些东西远程拥有的对象(例如指向对象的指针、网络或数据库连接的句柄等)。
唯一的例外情况是,如果您的对象包含某种缓冲区,并且您已经使用放置new将某些内容构造到该缓冲区中。如果使用放置new,则通常计划直接调用dtor。[请注意,“常见”可能过于夸张,因为您看到/使用这个的频率真的非常少,但其他可能性更为罕见。]

0

是的。即使您编写了析构函数,C++编译器也会创建一个序列。考虑以下代码:

class foo{
    int a;
}

编写一个析构函数,用于释放栈分配变量 a,这是不可能的。因此,即使您编写自己的析构函数,C++编译器也必须生成一个来释放栈对象。

1
如果你说 auto f = new foo;f.a 通常 不会 存储在堆栈上。 - cHao

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