多态析构函数:关于[conv.qual]中「相似类型」的困惑
C++ delete表达式标准条款疑问解答
首先引用标准条款内容:
在单对象delete表达式中,若待删除对象的静态类型与其动态类型不相似(见[conv.qual]),且所选的释放函数不是销毁式operator delete,则静态类型必须是动态类型的基类且拥有虚析构函数,否则行为未定义。在数组delete表达式中,若待删除对象的动态类型与其静态类型不相似,则行为未定义。
问题1:「不相似」的具体含义
根据[conv.qual]的定义,两个类型相似需满足两个核心条件:
- 去掉
const/volatile限定符后的底层类型完全一致; - 限定符的组合可通过限定转换兼容(比如
int和const int、volatile int*和const volatile int*这类,只是限定符数量不同,本质是同一底层类型的限定扩展)。
反之,「不相似」就是以下两种情况之一:
- 底层类型本身不同(比如
int和char、Base*和Derived*); - 限定符组合无法兼容(比如不存在合法的限定转换能让两个类型关联)。
问题2:基类指针与派生类指针是否属于相似类型
不属于。因为基类指针(如Base*)和派生类指针(如Derived*)去掉限定符后的底层类型分别是Base和Derived,是完全不同的类类型,不符合相似类型对底层类型必须一致的要求。
问题3:「所选的释放函数不是销毁式operator delete」的含义,以及默认析构函数的归属
核心概念区分
- 普通释放函数:仅负责回收内存,不执行对象析构,比如全局的
operator delete(void*)。 - 销毁式operator delete:是一类特殊的释放函数,会先确保对象的析构函数被调用,再回收内存,典型代表是类成员重载的
void operator delete(void*, std::destroying_delete_t)版本。
「所选的释放函数不是销毁式operator delete」,指当前delete表达式最终调用的是仅做内存回收的普通版本,而非带析构+回收语义的销毁式版本。
另外,类的默认析构函数不属于销毁式operator delete:析构函数的职责是销毁对象内部资源、调用成员/基类的析构;而销毁式operator delete是释放函数的分支,它的作用是在回收内存前触发析构,两者是完全不同的函数类型。
内容的提问来源于stack exchange,提问作者Aryan MP
相关产品推荐
相关产品推荐

