如果我没有为 C++ 类提供显式析构函数,因为我确信编译器提供的默认析构函数就是我的类所需要的,那可以吗?或者这被认为是不好的做法?
5 回答
仅在两种情况下需要显式析构函数:
当您需要运行时多态性时。在这种情况下,基类析构函数需要是
virtual
——这个要求强制你显式定义析构函数(即使它是空的!)。然而,派生类可能有也可能没有显式析构函数,这取决于它们是否管理资源(这是第二个要点)。当你的类是一个资源管理类时——也就是说,它实现了RAII idiom。在这种情况下,您可能还需要实现复制语义和移动语义。
在所有其他情况下,不需要显式定义的析构函数。:-)
提供显式析构函数的主要优点是您可以轻松地将断点放入其中以进行调试。有些人喜欢这样,因此更喜欢给每个类一个显式的析构函数。
但是,如果该类足够琐碎,很明显默认构造函数就足够了,那么省略它是完全可以的。另请注意,添加析构函数确实有其缺点:除了代码中的额外噪音之外,添加析构函数可能会阻止您的类成为POD。因此,您仍然应该避免在整个代码中盲目地散布琐碎的析构函数。
我认为省略一个空的非虚拟析构函数是有害的唯一情况是,为什么破坏是微不足道的(例如,如果三规则/五规则表明你需要一)。在这种情况下,我仍然会提供一个显式的空析构函数,并在正文中注释为什么不做任何事情是安全的。但这更多是个人喜好,而不是固定规则。
是的,这完全没问题。您自己提供析构函数主要有三个原因:
- 您正在定义类层次结构的基类,其对象将以多态方式销毁。然后,您需要定义析构函数 public 和virtual(和默认值,见下文)。
- 您正在定义一个层次结构中的基类,它不会以多态方式破坏其对象。由于在良好的 OO 实践中您不会实例化该基类的对象,因此您使析构函数成为非虚拟的、受保护的(和默认的)。
- 您正在定义一个拥有资源的类。您必须遵守五法则并定义析构函数以释放资源。
情况 1 和 2 是互斥的,而在情况 3 中,SRP 要求类的目的是单独管理拥有的资源,因此它不应该是基类,使得所有三种情况都互斥。这就是为什么基类析构函数和几乎所有“普通类”析构函数都应该默认的原因(参见这篇关于零规则的文章)。
当然,有许多极端情况并不完全适合该方案,并且在某些情况下需要析构函数。但通常,如果您确定默认析构函数执行所需的操作,则无需自己定义它。
在适用的情况下,如果出现以下情况,您通常应该提供不符合要求的定义:
析构函数是
virtual
,并且您的类没有提供任何不合规的虚拟定义(请记住,带有虚拟析构函数的基础构成您的析构函数virtual
)。许多实现在翻译中发出 vtables 和 RTTI 信息,其中包含第一个外线虚拟成员函数的定义。如果该类型对许多翻译可见,这可能会导致大量克隆信息。或者如果成员的破坏是“重量级的”
这两个可以减少你的二进制大小和构建时间。
您也可以将其定义为正确delete
的 PIMPL 成员(基于哪些标题在哪里可见以及您的智能指针的机制)。
这取决于您的构造函数在做什么。C++ 不提供垃圾回收,因此如果您的构造函数正在创建新对象,最好在析构函数中删除它们。无论如何都会释放用于类成员的内存,因此如果您没有在构造函数中使用“new”并且没有以任何其他方式分配内存,那么析构函数不是强制性的。