操作符重载之new与delete

        之前我是寡闻了,最近读书时,发现一个图表,上面的内容中发现new与delete是可以重载的,真的是出乎意料!居然还有这种操作,然后我在网上查了一下,看到几个简单的示例,作为学习方式,写下这篇博客巩固一下。

      没错,new与delete都是一种操作符,当我们在代码中new一个对象时,分为两步,首先是operator new的运作,就像C语言中的malloc一样,负责分配内存,然后是placement new的运作,负责给分配到的内存初始化(当我们给某个类重载new时,就是这个placement new调用的类构造函数)。其中前面那个负责分配内存的步骤,才是我们可以重载的new步骤,至于为什么要把new、delete设计成可以重载的样子,估计是为了提高C++的灵活性吧,比如我们自己编写的new和delete,可以加入一个统计内存申请次数和内存释放次数等。

      new重载的方式有两种,第一种是隐藏式重载,意思就是把本来提供给我们的new操作符版本给隐藏掉(这是我个人的猜测),这就意味着用这个方式重载new时,必须且只能给函数提供一个unsigned int型参数(size_t),因为正式的new版本有一个size_t类型参数,这个参数代表要申请的内存字节的大小;第二种方式是改变参数特征标,给operator new增加其他的参数,但是第一个参数必须得是size_t类型!

首先我们来看第一种类型的operator new重载示例:

#include <iostream>
using namespace std;

int i = 0;
void* operator new(size_t a)
{
	cout << "这是非常荒唐且危险的程序!" << endl;
	return &i;
}
int main()
{
	cout << "i的值是: " << i << endl;
	int *p = new int;
	*p = 9999;
	cout << "现在i的值却被意外改变了: " << i << endl;
	return 0;
}

运行结果会是:

【i的值是:0】

【这是非常荒唐且危险的程序!】

【现在i的值被意外改变了:9999】

正像示例中说的那样,这样的代码很不负责任!正确的做法应该是配合库函数malloc使用,但我想为了更好的诠释operator new重载的灵活性,所以还是写了这种烂代码来做说明。但在下面的代码示例中,我会将功补过,使用一种相对正确的做法来诠释operator new的多参数重载版本:

#include <iostream>
using namespace std;

int i = 1;//用来统计我们的new使用了多少次
void* operator new(size_t a,int b)
{
	cout << "这是我们第" <<i<<"次使用我们自己的new操作符"<< endl;
	i++;
	return malloc(a);
}
int main()
{
	int *p1 = new (i)int;//调用我们的new
	int *p2 = new int;//这个调用的是正式的new
	int *p3 = new (i)int;//调用我们的new
	return 0;
}

值得特别说明的是,在我们重载的函数中,i对应的是b,int(内容为4)对应的才是a,如果读者朋友有心,可以在函数中自己测试一下,这里不再赘述。


      以上两种new的重载,都是属于全局new的重载,但事实上,我们并没有重载全局new与delete的理由,因为正式的new,要比我们自己定义的new合理的多!C++之所以允许new能够被重载,主要是应付在我们自己的类上面,比如我们自己开发了一个类,如果在堆上给这个类开辟一个类对象时需要一些特殊的动作,那么我们应该给这个类域重载一个我们的new操作符,这样当我们new这个对象时会执行那些特殊的动作,下面就是代码,为了不文不对题,也有delete的重载示例(两个重载的操作符只对本类有效,对派生类无效,如果有派生类的话):

#include <iostream>
using namespace std;

class A 
{
public:
	int a;
	A() :a(0) {};
	void * operator new(unsigned i)//new的重载示例
	{
		cout << "调用我们自己的new操作符" << endl;
		if (i > sizeof(A))//如果调用此new的是派生类(大于A)
		{
			return ::operator new(i);//那么调用全局的正式new
		}
		return malloc(i);
	}
	void operator delete(void * p,size_t i)//第一个p代表要释放的首地址指针
	{
		cout << "调用我们自己的delete操作符" << endl;
		if (p)//检测指针是否为空,以防删除空指针报错!
		{
			if (i != sizeof(A))
			{
				return ::operator delete(p);
			}
			free(p);
		}
	}
};

int main()
{
	A * p(new (A));
	delete p;
	return 0;
}

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值