【修复世界观】之 C++的delete以及operator delete重载。

C++的delete以及operator delete重载。

朝花

刚学习c++的时候就学过在c++中delete/new其实都是一个方法,我们执行delete p其实就是调用了方法operator delete(p);
当然,还学过delete/new有全局的和局部的(类中的),我们可以重载他们,让delete和new按照我们想要的样子去执行对象的创建和销毁。
在过去这么多年中,我一直认坚定的认为我们代码中的delete p,等价于 operator delete(void*)。并幼稚的认为析构器的调用是在operator delete(void*)方法之后。

震惊!

为了维护一段年久的代码,我需要继承Base类创造一个新的Drive类,同时在现有代码中,之前用到Base类的地方都会在用完后delete pBase; 而新创造的Drive类是不需要/不能被释放的,这时候问题就来了:类似delete pBase;这样代码有成百上千处,分布在不同部门维护的不同模块代码中,真的没有办法去优雅的修改整个Base类的构造/释放用法。
于是,这时最简单粗暴的想法就是让delete pBase;在实例是Drive时失效。理所当然的想法就是重载operator delete,添加一个内部标记,只有标记为可释放时,delete才能真正的干活。

但,现实总是比想象骨感。

自信满满的编译代码,运行。程序并没有按照想要的样子运行。这时才发现:

delete pBase; 不是 Base::operator delete(pBase)
delete pBase; 不是 Base::operator delete(pBase)
delete pBase; 不是 Base::operator delete(pBase)

delete pBase中delete是一个c++关键字!

它在delete pBase这一表达式中,表示这里要销毁pBase指向的对象。
于是delete会先调用Drive的析构函数,然后是Base的析构函数,然后才是operator delete()的调用。这个顺序非常重要!operator delete()在析构函数之后调用!所以咱真的没法通过重载operator delete()来阻止delete pBase的执行。

当然,我们如果在析构函数和operator delete()中都添加一个标志,让他们什么事都不干呢?理论上这样确实可以阻止对象的销毁,更准确的说是delete pBase之后,pBase指向的对象还在内存空间上(win10 vs2012 x64 测试),但是c++标准对于这样的行为是没有定义的,(我们有找到,没有确切的证据能让我说服自己可以把这样的代码提交出去)。

做个总结吧

  • delete 是c++关键字,不能与delete操作符划等号。
  • delete关键字背后会调用析构函数和delete操作符方法,且析构函数执行在先。
  • 当你发现你的子类中的方法与父类同名方法的使用模式/行为模式不一致,这说明你的代码设计是有问题的。这时多态的封装事实上已经被破坏。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值