c++ 轻微破坏的意义

rsaldnfx  于 2023-02-01  发布在  其他
关注(0)|答案(3)|浏览(96)

在C++17中,如果T在[optional. object. dtor]中是可平凡析构的,那么新的std::optional要求它是可平凡析构的:
~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()发出代码。

tsm1rwdh

tsm1rwdh1#

std::optional已具有constexpr constructors。当其析构函数为平凡时,它是literal type。在常量表达式中只能创建和操作文本类型的对象。

vktxenjb

vktxenjb2#

一个类型可以被平凡地析构是它自己的回报。下面是拥有平凡析构函数的几个好处:
1.该类型可以简单地复制。这使得该类型可以进行各种优化。Visual Studio的标准库实现有一个number of optimizations来处理此类类型。
1.不调用可析构类型的析构函数是法律的的。你可以释放它们的存储空间。这是一个低级的事情,但是它有很多优点。它是允许实现进行上述优化的一部分。
1.具有平凡析构函数的类型可以是文本类型,因此是可以在编译时构造和操作的对象。
optional<T>的接口试图尽可能地不干扰T的行为。因此,如果您可以对T做一些事情,那么您应该可以对optional<T>做同样的事情。除非有一个非常好的理由不这样做。

5t7ly7z5

5t7ly7z53#

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

这绝对是更好的。

相关问题