【问题标题】:Why a "const T*" is trivially converted to "void*" in "operator delete"? [duplicate]为什么“const T*”在“operator delete”中被简单地转换为“void*”? [复制]
【发布时间】:2011-11-15 14:30:30
【问题描述】:

可能重复:
Deleting a pointer to const (T const*)

void operator delete (void*);
...
const char *pn = new char, *pm = (char*)malloc(1);
delete pn; // allowed !!
free(pm); // error

Demo.

free() 是一个函数是可以理解的,所以const void* 不能转换为void*。但是为什么在operator delete(默认或重载)的情况下允许呢?

它在功能上不是一个错误的构造吗?

【问题讨论】:

  • 删除void* 无论如何都是UB,所以谁在乎呢?
  • @tenfour,嗯,const T* 应该先转换为T*,然后再转换为void*。所以它不应该是UB。否则所有deletes 都是UB。
  • 哎呀,当然。我没有仔细阅读代码。

标签: c++ pointers constants free delete-operator


【解决方案1】:

不是。 delete 表达式首先调用析构函数。 之后 破坏,你留下一个void*。 (典型的实现, 事实上,有析构函数调用operator delete() 函数,因为 调用哪个operator delete() 取决于派生最多的类。)

至于为什么你的T const* 在析构函数中变成T*:这是任何 不同于:

{
    T const anObject;
    //  ...
} // destructor of anObject called here.  With T*, not T const*

?人们可以争论不同的规则,但最终,析构函数是 特殊,遵守特殊规则。

【讨论】:

  • 换句话说,毁灭抛弃了const
  • @MikeDeSimone:我以另一种方式看待它。 const 仅适用于活体。构造函数和析构函数在此生命周期之外执行,因此不适用于它们。
  • @MikeDeSimone 或者忽略它。无论如何,析构函数和构造函数都在玩类型游戏,那么还有什么异常呢?
【解决方案2】:

虽然我非常同意@JamesKanze 的回答,但也许有人想看看标准的实际含义。根据标准(§12.1/4):

const 和 volatile 语义 (7.1.5.1) 不适用于以下对象 建造。这种语义仅在最派生对象的构造函数(1.8)时生效 结束。

和(§12.4/2):

常量和 volatile 语义(7.1.5.1)不适用于正在销毁的对象。这样的语义不再存在 一旦最派生对象 (1.8) 的析构函数启动后生效。

公平地说,这只不过是重新陈述@James 所说的话,更具体一点:该对象仅在 ctor 完成(或 所有 ctors ,当涉及继承时)到第一个 dtor 开始的地步。在这些边界之外,不会强制执行 const 和 volatile。

【讨论】:

  • 存在细微差别。 James 说,“ 销毁后,你会留下一个void*。”标准说,“一旦最派生对象 (1.8) 的析构函数启动,这种语义就会停止生效。”因此,根据 James 所说,有人可以推断 const 语义在析构函数执行期间仍然有效,并且是错误的。不过,这真的很挑剔。
猜你喜欢
  • 1970-01-01
  • 2011-08-30
  • 2021-04-16
  • 1970-01-01
  • 2012-07-09
  • 2021-11-06
  • 1970-01-01
  • 1970-01-01
  • 2011-05-01
相关资源
最近更新 更多