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

2023-05-16

        最近做一个小项目,对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)了。

完整代码:
#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;
}

原文:http://hi.baidu.com/123az/item/d5a4768c2afee3c498255f18


笔者:Visual studio中使用CRT库来检测内存泄漏的原理就是重载全局的new、delete。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

c++ 中的重载全局new,delete 的相关文章

  • c#中new一个对象以后,是否需要手动释放?

    c 中new一个对象以后 xff0c 是否需要手动释放 xff1f 2012 04 28 23 43 wshbfzdzb 分类 xff1a C NET 浏览723次 c 43 43 中 class1 a 61 new class1 需要在用
  • delete this注意事项

    参考资料 在类中调用delete this问题
  • C ++的单例模式

    单例模式 对应一个类只能生成一个对象 include
  • Java—内部类

    It s possible to please a class definition within another class definition 内部类即定义在另一个类的内部的类 When you create an inner cla
  • JavaScript undefined 属性

    定义和用法 undefined 属性用于存放 JavaScript 的 undefined 值 语法 undefined 说明 无法使用 for in 循环来枚举 undefined 属性 也不能用 delete 运算符来删除它 undef
  • 通过修改注册表设置代理

    reg add HKCU Software Microsoft Windows CurrentVersion Internet Settings v ProxyEnable t REG DWORD d 1 f 作用 使用自动配置脚本 reg
  • 多表可更新视图的实现

    多表关联后的数据能保证主键唯一的视图是可直接做更新 不需要用触发器实现 多表视图的定义 当视图的数据源只有一张数据表 则该视图为单表视图 当视图的数据源是多张数据表 则该视图为多表视图 可更新视图的定义 在绝大多数人的概念中 视图是只读的
  • nafxcwd.lib和afxmem.obj的冲突

    gt Build started Project ReplaceOther Configuration Debug Win32 1 gt Linking 1 gt ImageTagInfo obj warning LNK4075 ignor
  • c++ 编码转化

    UTF 8到GB2312的转换 char U2G const char utf8 int len MultiByteToWideChar CP UTF8 0 utf8 1 NULL 0 wchar t wstr new wchar t le
  • C++沉思录读书笔记1.如何定义一个完整的类

    C 沉思录 Ruminations On C 读书笔记1 如何定义一个完整的类 作者 2006 4 27 12 19 C 哲学 只为用到的东西付出代价 定义一个类时必须搞清楚的几个问题 需要构造函数吗 如果答案为 no 那么很可能你需要定义
  • C++ malloc/free/new/delete详解(内存管理)

    这里写目录标题 malloc free 典型用法 内存分配 实现过程 brk和mmap 申请小于128k的内存 申请大于128k的内存 释放内存 brk和mmap的区别 new delete 典型用法 内存分配 实现过程 new delet
  • do...while(0)的妙用

    在C 中 有三种类型的循环语句 for while 和do while 但是在一般应用中作循环时 我们可能用for和while要多一些 do while相对不受重视 但是 最近在读我们项目的代码时 却发现了do while的一些十分聪明的用
  • C++学习之new 与 delete表达式

    new和delete表达式动态创建和释放单个对象 a 基本知识介绍 定义变量时 必须指定其数据类型和名字 而动态创建对象时只需指定其数据类型而不必为该对象命名 取而代之的是 new表达式返回新创建对象的指针 我们通过指针来访问此对象 int
  • C++并不难—之内存分配

    很多人都觉得学习C 是特别困难的事情 C 学习是比较复杂的 它的内存分配 指针 以及面向对象思想的实现等等 确实需要一定的技术积累 我们将以专题的形式 为大家逐一剖析c 的技术重点和难点 本专题讨论的就是内存分配 学习c 如果不了解内存分配
  • 关于C++对象模型(下)

    下篇主要讨论调用成员函数 访问成员变量的开销 及其特殊成员函数 数组 异常处理的讨论 这篇文章中出现的对象定义都出现在上篇中 全文在这里下载 文章内容转自 http tb blog csdn net TrackBack aspx PostI
  • 拷贝构造函数和赋值构造函数声明为私有的作用

    转贴地址 http blog csdn net winer632 archive 2009 01 12 3762292 aspx 每个类只有一个赋值函数 由于并非所有的对象都会使用拷贝构造函数和赋值函数 程序员可能对这两个函数有些轻视 请先
  • 解除Discuz!X2的15分钟锁定

    第一种方法 清两个failedlogin空表 解除用户锁定 mysql gt delete from pre common failedlogin Query OK 1 row affected 0 02 sec 解除UC用户锁定 mysq
  • C++面试题目集合(持续跟新)

    与我前面写的C语言进阶知识点遥相呼应 这才是C 面试 网上的面试题有些太简单了 C 面试题目最多集中在对象的内存模型 记住了 如果用c c 内存都不清楚 还写个屁的程序 1 C 的虚函数是怎样实现的 C 的虚函数使用了一个虚函数表来存放了每
  • C++ primer智能指针(HasPtr)实现

    智能指针显然是C 吸引人的地方之一 必须掌握 看了 C primer 里面着重讲了智能指针的实现方式 书中说到 HasPtr 注 就是自定义的智能指针 在其它方面的行为与普通指针一致 具体而言 复制对象时 副本和原对象将指向同一基础对象 如
  • enum与typedef enum的用法

    前些天发现了一个巨牛的人工智能学习网站 通俗易懂 风趣幽默 忍不住分享一下给大家 点击跳转到网站 https www captainai net db 一 两者的用法 枚举类型定义用关键字enum标识 形式为 enum 标识符 枚举数据表

随机推荐

  • Ubuntu+虚拟机 切换图形界面和命令行界面(亲测可行!!解决Ubuntu中快捷键失效问题!!)

    前几天做操作系统实验需要切换虚拟机的图形界面和命令行界面 在csdn上面找了各种方法 xff0c 比如快捷键Ctrl 43 Alt 43 F1 xff0c Ctrl 43 Alt 43 shift 43 F1等等 xff0c 虚拟机通通没有
  • 安装Kali Linux之后要做的前10件事

    Kali Linux是基于Debian的发行版 xff0c 由全球领先的信息安全培训公司之一 Offensive Security专门开发和维护 xff0c 用于高级渗透测试和安全性 它通常被称为黑客的理想操作系统 xff0c 它是对Bac
  • kafka 多消费者实现

    kafka官网 xff1a http kafka apache org quickstart 目录 kafka简单介绍 xff1a 实现方式 1 xff1a kafka分区 2 实现结果 3 xff1a kafka的consumer代码 4
  • ipa重签名的四种方式

    文章为学习hank的视频笔记 一 开发者调试安装app到手机的签名过程 1 Mac电脑生成公钥M和私钥M 2 公钥M传给苹果服务器 xff0c 苹果服务器的私钥A对公钥M进行加密生成证书返回给xcode 3 Xcode下载profile等描
  • IOS——使用ScrollView和PageController实现引导页分页效果

    如标题所说 xff0c 使用的是ScrollView和PageControlle两个控件共同达到该效果 首先 xff0c 使用storyboard将ScrollView和PageControlle拖入 xff0c 要注意的是 xff0c P
  • 寻找第一个出现次数最少的字符

    同理寻找第一个出现次数最少的字符 xff0c 一次循环的还没想好 span class hljs keyword import span java util HashMap span class hljs keyword import sp
  • 富文本

    ios项目中经常需要显示一些带有特殊样式的文本 xff0c 比如说带有下划线 删除线 斜体 空心字体 背景色 阴影以及图文混排 xff08 一种文字中夹杂图片的显示效果 xff09 通常想要实现这些效果要使用到iOS的Foundation框
  • 【设计模式】linux中利用信号量演示生产者与消费者模型

    1 简介 linux sem 信号量是一种特殊的变量 xff0c 访问具有原子性 xff0c 用于解决进程或线程间共享资源引发的同步问题 用户态进程对 sem 信号量可以有以下两种操作 xff1a 等待信号量 xff1a 当信号量值为 0
  • ftp与sftp上传工具类

    1 ftp上传工具类 package com zhjg utils import java io IOException import java io InputStream import java io OutputStream impo
  • 日本推出可实时监测地震烈度iPhone应用软件

    这个 xff0c 实在 xff01 据日本媒体报道 xff0c 日本近日在iPhone及iPad的平台上推出一款名为 i震度 的防灾害应用软件 该应用软件由专业研发地震检测仪器的白山工业公司开发完成 xff0c 具有随时随地监测地震烈度的功
  • Android 文件管理器 文件缩略图标显示流程

    前言 本篇文章是基于Android 11 文件管理器 xff08 com android documentsui xff09 的源码 xff0c 在实际项目中定位加载图片和视频文件显示缩略图的相关问题时 xff0c 做的总结 xff0c 文
  • Android 显示 指纹/人脸 身份验证对话框

    1 前言 为了增加用户的隐私和安全 xff0c 需保护您的应用中的敏感信息或付费内容 xff0c 一种方法是请求生物识别身份验证 xff0c 例如使用人脸识别或指纹识别 本篇文章介绍了如何在您的应用中支持生物识别登录流程 2 声明应用支持的
  • 截取图片部分

  • Android PackageManagerService总结(五) APK卸载流程

    一 概述 PackageManagerService 简称PKMS xff0c 是Android系统中核心服务之一 xff0c 管理着所有与package相关的工作 xff0c 常见的比如安装 卸载应用 信息查询等工作 主要完成以下核心功能
  • ButterKnife内存泄漏问题

    在butterKnife自动生成的代码 xff08 XXX ViewBinding xff09 中 xff0c 里面有这样一段代码 xff1a view setOnClickListener new DebouncingOnClickLis
  • PPTV面试算法思考-最长对称子字符串

    题目 最近在微信公众号里看看到了一个PPTV的面试算法题 xff0c 感觉难度适中 xff0c 想试下 题目的内容为求一个字符串的最长对称子字符串 如 xff1a 输入 输出 abba 4 abad 3 acccbaa 3 我的算法1 自己
  • C++

    由于见到论坛上不少找书的 xff0c 于是就稍稍汇总总结了一下 xff0c 作为本人即将推出的 C 43 43 资源大汇 系列文章的引子 本文只是初稿 xff0c 其中有不少的纰漏 笔误 打误 xff08 打字错误 xff09 希望各位纠正
  • pyspark MLlib基本使用

    MLib 基本概念 MLib其实就是将数据以RDD的形式进行表示 xff0c 在分布式数据集上调用各种算法 使用方法 MLlib中包含能够在集群上运行良好的并行算法 xff0c 如kmeans 分布式RF 交替最小二乘等 xff0c 这能够
  • 一个启动模式为singleTop的activity,如果再次启动会发生什么? 面试官想问的是 onNewIntent()

    Activity有一个 onNewIntent Intent intent 回调方法 xff0c 该方法我们几乎很少使用 xff0c 导致已经将其忽略掉 该方法的官方解释如下 xff1a This is called for activit
  • c++ 中的重载全局new,delete

    最近做一个小项目 xff0c 对c 43 43 又有很多新的理解 实在不的不让人发出感叹 xff0c c 43 43 太强大了 xff0c 绝对不是一朝一夕就可以领悟她的内涵的 首先我们要清楚 xff0c 为什么我们要重载new xff0c