【问题标题】:Does destroying delete still require destructor being accessible?销毁删除是否仍需要可访问析构函数?
【发布时间】:2020-12-27 01:04:21
【问题描述】:

C++20 引入了“销毁操作符删除”的概念,as described below

delete-expressions 在调用 operator delete 之前不会执行 *p 的析构函数

所以,给定以下struct S

struct S {
    void operator delete(S* p, std::destroying_delete_t);

private:
    ~S();
};

我希望下面的 delete 不会插入对析构函数的调用,而只是调用我们提供的销毁运算符 delete

delete new S;

但是,GCC/Clang/MSVC 的行为不同:DEMO

只有 GCC 不会尝试访问 ~S(),其他人仍然需要访问 ~S()

哪个是正确的?

【问题讨论】:

  • C++20 实现尚未完成,因此您应该在尝试依赖之前检查编译器声称支持的内容。
  • @NicolBolas 至少 cppreference 说这些编译器都支持它。

标签: c++ destructor delete-operator c++20


【解决方案1】:

gcc 是正确的:~S() 不需要可访问。

来自[expr.delete]/6

如果 delete-expression 的操作数的值不是空指针值并且所选的释放函数(见下文)不是破坏运算符 delete,则 delete-expression 将为正在删除的对象或数组的元素调用析构函数(如果有)。

只有在 not 破坏 delete 的情况下才会调用析构函数。事实上,这就是销毁 delete 的全部意义——让类作者控制如何/何时调用析构函数。因此,不要求析构函数是可访问的 - 调用它不取决于语言,这取决于用户。

【讨论】:

  • 这句话我也看过,但不确定是否足以判断标准不需要析构函数的可访问性。事实上,如果你将~S() 公开,Clang/MSVC 将不会调用析构函数,那么它们在技术上不符合吗?
  • @Jamboree 这是我们得到delete p; 必须调用析构函数的地方,没有其他地方会发生这种情况。即使没有调用,该语言通常也不要求可以访问函数。这绝对是clang的bug,我提交了47474
  • [expr.delete]p12:“对释放函数和析构函数(11.4.7、11.12)都进行了访问和歧义控制。”
猜你喜欢
  • 2021-05-30
  • 1970-01-01
  • 2013-10-29
  • 2014-01-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多