为什么"const T*"在"operator delete"中被简单地转换为"void*"?

Why a "const T*" is trivially converted to "void*" in "operator delete"?

本文关键字:简单 转换 void delete const operator 为什么      更新时间:2023-10-16

可能重复:
删除指向const(T const*(的指针

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

演示。

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

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

事实并非如此。delete表达式首先调用析构函数之后毁灭,你只剩下一个void*。(典型的实施方式,事实上,具有析构函数调用operator delete()函数,因为调用哪个operator delete()取决于最派生的类。(

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

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

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

虽然我非常同意@JamesKanze的回答,但也许有人想看看标准到底说了什么。根据标准(§12.1/4(:

const和volatile语义(7.1.5.1(不应用于建设这种语义只有在派生次数最多的对象的构造函数(1.8(之后才会生效结束。

和(§12.4/2(:

const和volatile语义(7.1.5.1(不应用于被破坏的对象。这样的语义不再存在一旦最派生对象(1.8(的析构函数启动,就生效。

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