重载全局new,delete

重载全局new,delete

 

对与new操作符,其实和sizeof一样,都是c++内置的,然而像strlen就不是了,strlen属于函数。对于new的功能我们是没有办法改变 的,当我们new一个对象时,new为我们做了两件事情,一、申请一块足够的内存空间供存放对象,对于new一个数组对象,编译器会计算出总共的空间,然 后执行类似c语言中malloc函数类似的功能。二、初始化对象,对于单个对象,包括包括基本对象和类对象,可以通过括号初始化,比如int * pn = new int(3); A * pa = new A(3);   然而对于数组不能初始化,对于类对象,必须定义无参数的构造函数。对与new的基本功能我们是无法改变的。

 

       我们所能改变的就是如何为对象分配内存,我们可一重载这个函数以实现分配内存。通常的重载方式是:

 

       void * operator new (size_t size);

 

       然而这已经足够了,在一般的operator new 重载函数里,我们可以再加入其它参数,但第一个参数必须是size_t类型,即为无符号整形。正是有这种特性,为我们对内存申请和释放的跟踪提供了可能。

 

 

       具体实现就是第一个operator new 的重载函数,我们第一的这个函数是这样的:

 

void * operator new(unsigned int size, const char *file, int line)

{

    cout << "new size:" << size << endl;

    cout << file << " " << line << endl;

 

    void * p = malloc(size);

 

    return p;

}

 

       然后用宏替换所有的new:

 

#define new new(__FILE__, __LINE__)

 

       这样我们每次调用new,比如int * pn = new int;被编译器替换成了int * pn = new (__FILE__, __LINE__) int,从而调用我们定义的operator new,这种办法确实很妙。需要交代的是,对于数组同样适用,而是在编译的是后由编译器计算出所需要的长度调用我们定义的operator new函数。

 

       对于delete,我们无需使用宏定义,只要重载operator delete就可以了,然而我们需要重载两个delete:

 

void operator delete(void * p)

{

    cout << "delete " << (int)p << endl;

    free(p);

}

 

void operator delete [] (void * p)

{

    cout << "delete [] " << (int)p << endl;

    free(p);

}

 

 

       其实后面一个函数的内容和前面的内容一样,但为了支持数组的释放,我们必须是要定义的。那么我们只是简单的free(p)编译器咋知道我们释放的数组,还 是单个对象了,这个不用我们操心了,我们只要提供给free函数一个申请内存的首地址就可以了。因为在用malloc申请的时候,我们也把数组装换为内存 大小了。

 

       由此我们可以得出下面的推断:用int * pn = new int [100];的空间,用delete pn释放和delete [] pn释放效果一样。然而那么既然这两种方式一样,那还要delete [] 干什么,其实delete [] 有另外的作用就是类对象数组的释放,编译器把delete []解释为调用对象的析构函数,这个是通过循环实现的,最后释放掉申请的内存。

 

       既然我们已经跟踪了new和delete,那么就可以比较容易的判断申请的内存是否最后得到释放,要完成它,我们还需要一个链表,或者其它,当我们申请一 块内存的时候加入到链表中,释放一块空间的时候,从链表中删除和释放内存首地址相同的节点就可以了,最后理想的情况是链表为空,如果不为空,那就说明内存 发生泄露(Memory leaks)了。

 

完整代码:

 

#include "malloc.h"

#include "iostream.h"

 

#ifdef _DEBUG

 

void * operator new(unsigned int size, const char *file, int line)

{

    cout << "new size:" << size << endl;

    cout << file << " " << line << endl;

 

    // 下面两种方法可以达到同样的效果,但下面一种比较好

    // 因为用下面一种可以保持原有的申请方式一样

    //void * p = malloc(size);

    void * p = operator new(size);

 

    return p;

}

 

void operator delete(void * p)

{

    cout << "delete " << (int)p << endl;

    free(p);

}

 

void operator delete [] (void * p)

{

    cout << "delete [] " << (int)p << endl;

    free(p);

}

 

void operator delete(void * p, const char *file, int line)

{

    cout << "delete file line" << endl;

    free(p);

}

 

void operator delete [] (void * p, const char *file, int line)

{

    cout << "delete [] file line" << endl;

    free(p);

}

 

#define new new(__FILE__, __LINE__)

#endif

 

void main()

{

    int * p = new int[5];    

    delete [] p;

// delete p;

}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值