【问题标题】:Significance of trivial destruction琐碎破坏的意义
【发布时间】:2017-06-13 08:07:20
【问题描述】:

在 C++17 中,新的 std::optional 规定如果 T 在 [optional.object.dtor] 中可简单破坏,则它可简单破坏:

~optional();
1 效果:如果is_trivially_destructible_v<T> != true*this 包含一个值,则调用val->T::~T()
2 备注:如果is_trivially_destructible_v<T> == true 那么这个析构函数应该是一个普通的析构函数。

所以这个潜在的实现片段将不符合标准:

template <class T>
struct wrong_optional {
    union { T value; };
    bool on;

    ~wrong_optional() { if (on) { value.~T(); } }
};

我的问题是:这个授权有什么好处?据推测,对于一般可破坏的类型,编译器可以确定value.~T() 是无操作的,并且不会为wrong_optional&lt;T&gt;::~wrong_optional() 发出任何代码。

【问题讨论】:

  • 其他类型可能依赖于给定类型是否可以简单破坏的事实。 (作为std::vector 的破坏?)。

标签: c++ destructor c++17


【解决方案1】:

std::optional 已经有constexpr constructors。当它的析构函数很简单时,它是一个literal type。只有文字类型的对象才能在常量表达式中创建和操作。

【讨论】:

  • 如果测试微不足道的破坏性的目的是看它是否是文字类型,为什么不改用 std::is_literal_type 呢?
  • std::is_literal_type 在引入std::optional 时已被弃用。 (std::is_literal_type 现在在 C++20 中被删除。)
  • @YongweiWu 这对这个答案没有影响。
  • @cpplearner 对不起,我是想回复第一条评论。
【解决方案2】:

一个可以简单破坏的类型是它自己的奖励。以下是使用微不足道的析构函数的一些优点:

  1. 该类型可以很容易地复制。这使得该类型有资格进行各种优化。 Visual Studio 的标准库实现有一个number of optimizations 用于处理此类类型。

  2. 不必费心调用可破坏类型的析构函数是合法的。您可以只释放他们的存储空间。这是一种低级的事情,但它可以有优势。这是允许实现进行上述优化的一部分。

  3. 带有普通析构函数的类型可以是文字类型,因此是可以在编译时构造和操作的对象。

optional&lt;T&gt; 的接口试图尽可能不干扰T 的行为。所以如果你可以用T 做某事,那么你应该可以用optional&lt;T&gt; 做同样的事情。除非有充分的理由不这样做。

【讨论】:

  • 关于 (1),std::optional&lt;T&gt; 并没有被强制要求可以轻松复制。你觉得应该吗?
  • @Barry:更好的问题是“可以吗”?答案是否定的,它不能。 optional 实际上包含一个“布尔值”和一些 sizeof(T) 字节的存储,这些字节可能会或可能不会被初始化为包含对象。如果传入的存储包含一个对象,仅仅对它进行位复制不会导致目标存储包含一个对象。如果T 可以简单地破坏,optional 仍然可以简单地破坏,但不能简单地复制。
  • 如果T 可简单复制,您可以实现optional&lt;T&gt; 使其可简单复制。
  • @Barry:“答案是否定”的哪一部分你不明白;)
  • 我认为你错的部分? union { char; T; } bool; 可以轻松复制。
【解决方案3】:

Per this Q/A,一个尚未提及但值得一提的具体原因是:可简单复制和可简单破坏的类型允许它在 ABI 中的寄存器中传递(请参阅Agner Fog's calling conventions)。这会对生成的代码产生重大影响。一个简单的函数,如:

std::optional<int> get() { return {42}; }

如果类型不是一般可复制/可破坏的,可能会发出以下代码:

    mov     rax, rdi
    mov     DWORD PTR [rdi], 42
    mov     BYTE PTR [rdi+4], 1
    ret

但如果是的话,可能会发出以下内容:

    movabs  rax, 4294967338
    ret

那肯定更好。

【讨论】:

    猜你喜欢
    • 2012-07-31
    • 1970-01-01
    • 2016-03-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-01
    • 1970-01-01
    相关资源
    最近更新 更多