琐碎毁灭的意义

时间:2017-01-27 15:26:08

标签: c++ destructor c++17

在C ++ 17中,如果std::optional在[optional.object.dtor]中可以轻易破坏,则新T强制要求它是可以轻易破坏的:

  

~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<T>::~wrong_optional()发出代码。

3 个答案:

答案 0 :(得分:15)

std::optional已有constexpr constructors。当它的析构函数是微不足道的时候,它是literal type。只能在常量表达式中创建和操作文字类型的对象。

答案 1 :(得分:9)

一种可以轻易破坏的类型是它自己的奖励。以下是使用简单析构函数的一些优点:

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

  2. 不打扰调用易于破坏的类型的析构函数是合法的。您只需取消分配存储空间即可。这是一种低级别的事情,但它可以有优势。它是允许实现进行上述优化的部分原因。

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

  4. optional<T>的界面试图尽可能不干扰T的行为。因此,如果您可以使用T执行某些操作,那么您应该能够使用optional<T>执行相同的操作。除非有充分的理由不这样做。

答案 2 :(得分:0)

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

那肯定更好。