在调用其析构函数之前,是否有任何实际理由检查某些东西是否可破坏?

Is there any practical reason to check if something is destructible before calling its destructor?

本文关键字:是否 检查 理由 可破坏 任何实 析构函数 调用      更新时间:2023-10-16

所以我一直在尝试实现变体/标记的联合类,需要一种方法来编写泛型析构函数,并犯了一个我认为是愚蠢的错误,忘记了某些类型没有析构函数,做类似的事情

template<typename T> 
void destruct(T& thing) {
thing.~T();
}

然而,即使对于没有析构函数的类型(如intstruct A {int b;};(,这也工作正常。我仍然认为使用这样的东西更具可读性,更容易推理

template<typename T>
void destruct(T& thing) {
if constexpr(std::is_destructible<T>::value) {
thing.~T();
}
}

但是代码之间真的有什么区别吗?第一个对我来说感觉很不确定的行为/只是错误。

然而,即使对于没有析构函数的类型,如 int 或结构 A {int b;},这也工作正常;

这些是微不足道的可破坏类型的示例。调用它们的"析构函数"是很好的定义。它没有任何影响。

但是代码之间真的有什么区别吗?

仅适用于不可破坏的类型。平凡可破坏的类型是可破坏的。

对于不可破坏的类型,如void、函数类型或具有~T() = delete;的类型,前一个函数的格式不正确,而后者的格式良好,主体为空。这取决于用例哪个更有用,但默默忽略破坏不可破坏的东西的尝试对我来说似乎是可疑的。

你不需要检查。在此上下文中,对于像int这样的类型,它转换为伪析构函数调用。结果是几乎无操作

[伪证]

1 在点 . 或箭头 ->运算符后使用伪析构函数名称表示非类类型的析构函数,表示为 类型名称或描述符。结果只能用作 函数调用运算符 (( 的操作数以及此类 调用的类型为 void。唯一的效果是评估 点或箭头之前的后缀表达式。

2 点运算符的左侧应为标量类型。这 箭头运算符的左侧应指向标量 类型。此标量类型是对象类型。简历不合格版本 对象类型和由 伪析构函数名称应为同一类型。此外,两者 表单的伪析构函数名称中的类型名称

嵌套名称说明符opt

类型名称 :: ~ 类型名称应指定相同的标量类型(忽略 CV 限定(。

这种表达故意存在于语言中,以便使泛型代码的编写更容易。所以你的destruct没有if很好.

顺便说一句,您可能有兴趣知道标准库具有这样的功能。这是std::destroy_at.除了将数组作为特殊情况处理之外,它几乎可以完成您已经执行的操作。