zoukankan      html  css  js  c++  java
  • ZT c++ 中的重载全局new,delete

    c++ 中的重载全局new,delete

    分类: c++ 116人阅读 评论(1) 收藏 举报

    最近做一个小项目,对c++又有很多新的理解。实在不的不让人发出感叹,c++太强大了,绝对不是一朝一夕就可以领悟她的内涵的。

           首 先我们要清楚,为什么我们要重载new,和delete了?这还不是指针造成的,确实指针是一件让人喜欢的东西,用起来如此让人喜欢,让人顺手。然而小程 序我们完全可以避免内存泄露问题,大程序就不那么容易了,然而我们有一种特别好的方法可以跟踪我们new,和delete动作,找到未被释放的内存。办法 是什么呢?微软给我们提供了一种很好的方法,那就是重载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)了。

    完整代码:

    1. #include "malloc.h"  
    2. #include "iostream.h"  
    3. #ifdef _DEBUG  
    4. void * operator new(unsigned int size, const char *file, int line)  
    5. {  
    6.     cout << "new size:" << size << endl;  
    7.     cout << file << " " << line << endl;  
    8.     // 下面两种方法可以达到同样的效果,但下面一种比较好  
    9.     // 因为用下面一种可以保持原有的申请方式一样  
    10.     //void * p = malloc(size);  
    11.     void * p = operator new(size);  
    12.     return p;  
    13. }  
    14. void operator delete(void * p)  
    15. {  
    16.     cout << "delete " << (int)p << endl;  
    17.     free(p);  
    18. }  
    19. void operator delete [] (void * p)  
    20. {  
    21.     cout << "delete [] " << (int)p << endl;  
    22.     free(p);  
    23. }  
    24. void operator delete(void * p, const char *file, int line)  
    25. {  
    26.     cout << "delete file line" << endl;  
    27.     free(p);  
    28. }  
    29. void operator delete [] (void * p, const char *file, int line)  
    30. {  
    31.     cout << "delete [] file line" << endl;  
    32.     free(p);  
    33. }  
    34. #define new new(__FILE__, __LINE__)  
    35. #endif  
    36. void main()  
    37. {  
    38.     int * p = new int[5];     
    39.     delete [] p;  
    40. // delete p;  
    41. }  
     
     
    #include "malloc.h"  
    #include "iostream"
    #include "stdlib.h"
    #include "stdio.h"
      
    using namespace std;
    #define _DEBUG   
    
    #ifdef _DEBUG  
    
        void * operator new[](std::size_t 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 new(std::size_t 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 " << reinterpret_cast<int>(p) << endl;  
    		cout << "delete " << p << endl;  
            free(p);  
        }  
        void operator delete [] (void * p)  
        {  
            //cout << "delete [] " << static_cast<int> ( p ) << endl;  
    		cout << "delete [] " <<  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  
        int main()  
        {  
            int * p = new int[5];     
            delete [] p;  
    
            int * p2 = new int;     
            delete p2; 
    
    		return 0;
        }  
    

    end$ ./1
    new[] size:20
    newoverload.cpp 58
    delete [] 0x23b4010
    new size:4
    newoverload.cpp 61
    delete 0x23b4010

     
     
     
     
  • 相关阅读:
    基于layui的简易后台管理系统,后期会更新
    java基础语法知识(笔记)——(一)基本变量类型,循环,日期类
    JavaWeb学习总结(笔记)——SSM spring.xml的基本配置
    JavaWeb学习总结(笔记)——SSM中Web.xml文件
    JavaWeb学习总结(笔记)——SSM关键类及其作用
    JavaWeb学习总结(笔记)——关于SSM CRUD上传功能的总结
    JavaWeb——MVC与三层结构
    jquery结合highcharts插件显示实时数据动态曲线图
    jquery结合Highcharts插件实现动态数据仪表盘图形化显示效果
    在IE6/7下表格td标签没有内容时不显示边框?
  • 原文地址:https://www.cnblogs.com/jeanschen/p/3425826.html
Copyright © 2011-2022 走看看