为什么普通的可复制类要求析构函数必须是普通的

Why trivial copyable class require the destructor must be trivial

本文关键字:析构函数 可复制 为什么      更新时间:2023-10-16

基于c++标准。平凡的可复制类定义如下:根据9/5,

A trivially copyable class is a class that:
- has no non-trivial copy constructors (12.8),
- has no non-trivial move constructors (12.8),
- has no non-trivial copy assignment operators (13.5.3, 12.8),
- has no non-trivial move assignment operators (13.5.3, 12.8), and
- has a trivial destructor (12.4).

根据我的理解,平凡可复制的类是可以按位复制的。那么,为什么需要平凡的析构函数呢?

与按位复制无关。

原因很简单。trivial copyable意味着在对象B之上复制一个对象A是有效的,并且定义了行为。显然,B的析构函数不会被调用,所以它必须是平凡的。

在N3797 3.8/4中有一个对象生命周期的描述,似乎涵盖了这种情况。但是,如果程序不依赖于析构函数的副作用,则可能存在关于存储重用和不调用非平凡析构函数的漏洞。

一个重要的析构函数可能意味着您正在删除一些指针。如果是这种情况,对类进行按位复制似乎很容易出错,因为这样就会有两个实例都试图删除同一个指针。

这只是一个猜测

在c++对象模型中,满足Trivially Copyable概念的类型在逻辑上是数据只是位块的类型。类型只是具有一些值的基本数据对象的集合。因此,将一个位块复制到某个存储是一个完全有效的操作,并且该存储(如果正确对齐)现在应该包含这样一个对象。此外,将一个位块复制到某个临时存储(不管对齐方式如何),然后将其复制回适当类型的对象,这是完全合理的。

c++允许所有这些对于平凡可Copyable类型。

如果一个类型真的只是一个比特块…为什么它的销毁不仅仅涉及内存释放?或者更重要的是,如果它的销毁需要做的不仅仅是释放内存,那么真的只是一个比特块吗?

c++的答案是否定的,它不是。或者更确切地说,我们不能证明它不仅仅是一个比特块。

这就是琐碎可复制性规则:它是关于证明的。在平凡的可复制性规则下,我们可以证明这样的类型只是一个比特块。其他类型可能是位块,这取决于这些函数的作用。但由于我们无法证明它们是否存在,因此我们禁止这样对待它们。

相关文章: