在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()
发出代码。
3条答案
按热度按时间tsm1rwdh1#
std::optional
已具有constexpr
constructors。当其析构函数为平凡时,它是literal type。在常量表达式中只能创建和操作文本类型的对象。vktxenjb2#
一个类型可以被平凡地析构是它自己的回报。下面是拥有平凡析构函数的几个好处:
1.该类型可以简单地复制。这使得该类型可以进行各种优化。Visual Studio的标准库实现有一个number of optimizations来处理此类类型。
1.不调用可析构类型的析构函数是法律的的。你可以释放它们的存储空间。这是一个低级的事情,但是它有很多优点。它是允许实现进行上述优化的一部分。
1.具有平凡析构函数的类型可以是文本类型,因此是可以在编译时构造和操作的对象。
optional<T>
的接口试图尽可能地不干扰T
的行为。因此,如果您可以对T
做一些事情,那么您应该可以对optional<T>
做同样的事情。除非有一个非常好的理由不这样做。5t7ly7z53#
Per this Q/A,一个尚未提及但值得一提的具体原因是:一个类型可以简单地复制和析构,允许它在ABI的寄存器中传递(参见Agner Fog's calling conventions)。这对生成的代码有很大的影响。一个简单的函数如下:
如果类型不是可复制/可析构的,则可能发出以下代码:
但如果是的话,可能只会发出以下信号:
这绝对是更好的。