Significance of trivial destruction

岁酱吖の 提交于 2019-12-23 06:57:14

问题


In C++17, the new std::optional mandates that it be trivially destructible if T is trivially destructible in [optional.object.dtor]:

~optional();
1 Effects: If is_trivially_destructible_v<T> != true and *this contains a value, calls val->T::~T().
2 Remarks: If is_trivially_destructible_v<T> == true then this destructor shall be a trivial destructor.

So this potential implementation fragment would be non-conforming to the standard:

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

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

My question is: what is the advantage of this mandate? Presumably, for trivially destructible types, the compiler can figure out that value.~T() is a no-op and emit no code for wrong_optional<T>::~wrong_optional().


回答1:


std::optional already has constexpr constructors. When its destructor is trivial, it is a literal type. Only objects of literal types can be created and manipulated in constant expressions.




回答2:


A type being trivially destructible is its own reward. Here are just a few of the advantages of having a trivial destructor:

  1. The type can be trivially copyable. And this make the type eligible for all kinds of optimizations. Visual Studio's standard library implementation has a number of optimizations for dealing with such types.

  2. It's legal to not bother calling the destructor of trivially destructible types. You can just deallocate their storage. This is kind of a low-level thing to do, but it can have advantages. It's part of what allows implementations to do those optimizations above.

  3. Types with trivial destructors can be literal types, and are thus objects which can be constructed and manipulated at compile time.

optional<T>'s interface is attempting not to interfere with the behavior of T as much as possible. So if you could do something with T, then you ought to be able to do that same thing with optional<T>. Unless there is a really good reason not to.




回答3:


Per this Q/A, one specific reason not yet mentioned and worth mentioning is: a type being trivially copyable and trivially destructible allows it to be passed in registers in the ABI (see Agner Fog's calling conventions). This can have significant effects on the generated code. A simple function like:

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

Might emit the following code if the type isn't trivially copyable/destructible:

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

But could emit just the following if it were:

    movabs  rax, 4294967338
    ret

That's definitely better.



来源:https://stackoverflow.com/questions/41897418/significance-of-trivial-destruction

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!