【问题标题】:Why trivial copyable class require the destructor must be trivial为什么琐碎的可复制类要求析构函数必须是琐碎的
【发布时间】:2014-03-19 01:15:14
【问题描述】:

基于 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).

据我了解,可简单复制的类是可以按位复制的。 那么需要与按位复制无关的琐碎析构函数的直觉和理由是什么。

【问题讨论】:

  • 至少有一个点是virtual destructor

标签: c++ language-lawyer


【解决方案1】:

原因很简单。 Trivially copyable 意味着将一个对象 A 复制到另一个 B 之上是有效且已定义的行为。显然 B 的析构函数不会被调用,因此它必须是琐碎的。

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

【讨论】:

    【解决方案2】:

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

    这只是猜测

    【讨论】:

    • 但你也可以在其他成员函数中删除它,而不是按位复制后的析构函数。需要非平凡的析构函数不能解决这个问题。
    【解决方案3】:

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

    C++ 允许对 Trivially Copyable 类型进行所有这些操作。

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

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

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

    【讨论】:

      猜你喜欢
      • 2020-11-19
      • 2012-07-31
      • 2010-10-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-06-13
      相关资源
      最近更新 更多