You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何基类指针删除单个对象与数组时delete运算符调用行为不同?

C++中delete单个对象与delete数组的operator delete调用差异解析

示例代码

#include <iostream>
using namespace std;
struct A 
{
    virtual ~A() {  cout << "~A ";};
    void operator delete(void* p) 
    {
        cout << "A :: operator delete" << endl;
    }
    
    void operator delete[](void* p) 
    {
        cout << "A :: operator delete[]" << endl;
    }
};
struct B : A 
{
    ~B(){ cout << "~B ";}
    void operator delete(void* p) 
    {
        cout << "B :: operator delete" << endl;
    }
    void operator delete[](void* p) 
    {
        cout << "B :: operator delete[]" << endl;
    }
};
int main() 
{
    A* ptr1 = new B;
    A* ptr2 = new B[2];
    delete ptr1;
    delete [] ptr2;
}

运行输出

~B ~A B :: operator delete
~B ~A ~B ~A A :: operator delete[]

行为差异原因解析

1. 单个对象的delete逻辑

当执行delete ptr1时:

  • 因为基类A声明了虚析构函数,编译器会通过虚表机制定位到对象的实际类型(B),先调用B的析构函数,再调用A的析构函数。
  • 完成析构后,C++标准规定,对于多态类的单个对象删除操作,会继续通过虚表关联的机制,调用实际类型(B)对应的operator delete,这也是输出中出现B :: operator delete的原因。

2. 数组对象的delete[]逻辑

当执行delete[] ptr2时:

  • 虽然虚析构函数保证了每个数组元素都能正确调用B和A的析构函数(因此输出两次~B ~A),但**operator delete[]并不支持虚函数动态绑定**。
  • C++标准未将数组删除函数纳入虚函数体系,编译器会直接根据指针的静态类型(即A*)来选择对应的operator delete[],而非对象的动态类型(B)。因此最终调用的是基类A的operator delete[]。
  • 底层原因是:数组内存分配时,会在数组头部存储元素个数等元信息,但这些信息不包含用于动态选择operator delete[]的虚表指针或类似机制,无法像单个对象那样完成动态绑定。

内容的提问来源于stack exchange,提问作者Hardik

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 17:12:43