文章目录

  • 一.new运算符说明
    • 1.作用
    • 2.标准库函数
    • 3.运行原理:
    • 4.常见用法:
    • 5.size_t如何传递
  • 二.delete函数
    • 1.作用
    • 2.标准库函数
    • 3.运行原理:
    • 4.常见用法:
  • 三.自定义new和delete
    • 1.自定义规范:
    • 2.代码示例
    • 3.测试结果
  • 4.参考文献:

一.new运算符说明

1.作用

  • 动态申请内存

2.标准库函数

//会抛异常版本:
void *operator new(size_t);  //分配一个对象
void *operator new[](size_t);//分配一个数组
//不会抛异常版本:
void *operator new(size_t,nothrow_t&) noexcept;
void *operator new[](size_t,nothrow_t&) noexcept;

3.运行原理:

  • 1.通过malloc分配size_t参数指定大小的内存;
  • 2.对这块内存进行初始化(类的构造,基本类型初始化或者清0);

4.常见用法:

struct A
{int _val;
};
A*p = new A;                   //方式一
A *p = new A();                //方式二
A *pArray = new A[10];         //方式三
void *pMem = malloc(sizeof(A));//方式四
A *p = new(pMem) A;
  • 第一种方式申请内存空间后不会清零,如果未对变量做初始化就直接使用,存在脏数据风险;
  • 第二种方式相比第一种增加了(),这会导致在执行完内存分配后,系统会对内存进行清零,弊端是内存清零必然会损耗性能。
  • 第三种方式是用来创建对象数组的,不多说;
  • 最后一种是placement new的写法,这种写法的特点是:
    ①需要先通过malloc等函数申请到所需要大小的内存空间;
    ②通过void *operator new(size_t,void*)的这种placement new的写法,直接在malloc申请到的内存空间进行构造或者初始化;
    这种申请方式一个很显然的优势在于内存的重复利用,如果使用场景中存在一个对象需要频繁创建和销毁,推荐使用这种方式。

    5.size_t如何传递

  • 我们可以看到new操作符的定义中第一个参数是size_t类型的,但是我们实际使用中并没有去指定参数,那这个参数是怎么传递下去的呢?实际上当编译器在处理operator new时,会将存储指定指定对象内存大小传递给new函数的第一个参数。同样的,当调用operator new[]时,编译器会将存储指定对象数组所需的内存空间传递到new[]函数的第一个参数。
  • 后面我们会看到如果我们自定义了new操作符,并且带有额外参数,调用时传递的第一个参数实际上会传递到operator new(size_t,args…)函数的第二个形参里面去。

二.delete函数

1.作用

  • 释放通过new动态申请的内存空间,和new配套使用;

2.标准库函数

//会抛异常版本
void operaor delete(void *pObj);    //释放对象所占用的空间
void operator delete[](void *pArrayObj); //释放对象数组所占用的空间
//不会抛异常版本
void operator delete(void *pObj, nothrow_t&) noexcept;
void operator delete[](void *pArrayObj, nothrow_t&) noexcept;

3.运行原理:

  • 1.调用对象的析构函数;
  • 2.释放空间;

4.常见用法:

struct A
{int _val;
}
A *p = new A;
delete(p);      //释放单个对象
A *pArray = new A[10];
delete[](pArray);//释放对象数组

三.自定义new和delete

1.自定义规范:

operator new/delete进行自定义可以实现为类的方法或者全局方法。
如果在类的方法中自定义了operator new/delete,则在new该对象时会优先调用类中的自定义方法。如果全局也有自定义的接口,则可以通过使用限定符::来调用全局的自定义接口。

2.代码示例

#include <iostream>
#include <malloc.h>
#include <new>
#include <cassert>
#include <string>void *operator new(size_t size)
{std::cout << "global new enter" << std::endl;return malloc(size);
}void *operator new[](size_t size)
{std::cout << "global new array enter" << std::endl;return malloc(size);
}void operator delete(void *pObj)
{std::cout << "global delete enter" << std::endl;free(pObj);
}void operator delete[](void *pObjArray)
{std::cout << "global delete array enter" << std::endl;free(pObjArray);
}class MemoryDemo
{
public:MemoryDemo() = default;~MemoryDemo() = default;void* operator new(size_t size){std::cout << "new enter" << std::endl;return malloc(size);}void *operator new[](size_t size){std::cout << "new array enter" << std::endl;return malloc(size);}void *operator new(size_t size, int mode){std::cout << "new with mode:" <<mode << " enter" << std::endl;return malloc(size);}void *operator new[](size_t size, int mode){std::cout << "new array with with mode:" <<mode << " enter" << std::endl;return malloc(size);}void operator delete(void *pObj){std::cout << "delete enter" << std::endl;free(pObj);}void operator delete[](void *pObjArray){std::cout << "delete array enter" << std::endl;free(pObjArray);}
};int main()
{//测试class重写new和deleteMemoryDemo *pDemo = new MemoryDemo;assert(pDemo != nullptr);delete(pDemo);std::cout << "---------------------------------" << std::endl;//测试class重写new[]和delete[]MemoryDemo *pArrayDemo = new MemoryDemo[10];assert(pArrayDemo != nullptr);delete[](pArrayDemo);std::cout << "---------------------------------" << std::endl;//测试全局重写new和deleteMemoryDemo *pGlobalDemo = ::new MemoryDemo;assert(pGlobalDemo != nullptr);::delete(pGlobalDemo);std::cout << "---------------------------------" << std::endl;//测试class重写new(带额外参数)MemoryDemo *pModeDemo = new(1) MemoryDemo;assert(pModeDemo != nullptr);delete(pModeDemo);std::cout << "---------------------------------" << std::endl;//测试class重写new[](带额外参数)MemoryDemo *pModeArrayDemo = new(2) MemoryDemo[10];assert(pModeArrayDemo != nullptr);delete[](pModeArrayDemo);return 0;
}

3.测试结果

4.参考文献:

【Primer C++ 第五版】

学习笔记:c++ newdelete关键字及其自定义相关推荐

  1. linux添加自己的库,Linux学习笔记——例叙makefile 增加自定义共享库

    Linux学习笔记--例说makefile 增加自定义共享库 0.前言 从学习C语言开始就慢慢开始接触makefile,查阅了很多的makefile的资料但总感觉没有真正掌握makefile,如果自己 ...

  2. ROS 学习笔记(三):自定义服务数据srv+server+client 示例运行

    ROS 学习笔记(三):自定义服务数据srv+Server+Client 示例运行 一.自定义服务数据: 1.向功能包添加自定义服务文件(AddTwoInts.srv) cd ~/catkin_ws/ ...

  3. Polyworks脚本开发学习笔记(十七)-制作宏脚本自定义工具条

    Polyworks脚本开发学习笔记(十七)-制作宏脚本自定义工具条 做好的宏脚本程序,每次打开脚本加载程序太多麻烦,为了方便的调用脚本做各种操作,可以使用系统的自定义工具条功能将脚本加载到工具条上. ...

  4. VSTO 学习笔记(十二)自定义公式与Ribbon

    原文:VSTO 学习笔记(十二)自定义公式与Ribbon 这几天工作中在开发一个Excel插件,包含自定义公式,根据条件从数据库中查询结果.这次我们来做一个简单的测试,达到类似的目的. 即在Excel ...

  5. Dynamic CRM 2013学习笔记(三十三)自定义审批流4 - 规则节点 -有分支的流程处理...

    上次介绍过节点的基本配置<Dynamic CRM 2013学习笔记(三十二)自定义审批流3 - 节点及实体配置>,这次介绍下规则节点,因为有时流程里会有一些分支.合并,这时就要用到规则节点 ...

  6. SpringBoot学习笔记(4):自定义的过滤器

    SpringBoot:学习笔记(4)--自定义的过滤器 快速开始 SpringBoot提供的前端控制器无法满足我们产品的需求时,我们需要添加自定义的过滤器. 在SpringBoot的开发中,我们应该还 ...

  7. 【多线程学习笔记】sychronized关键字底层原理、sychronized与ReentrantLock、volatile和synchronized

    文章目录 sychronized释义 synchronized关键字最主要的三种使用方式: synchronized底层原理: 同步代码块: 同步方法 当前类的class对象作为锁 锁升级 Synch ...

  8. Go 学习笔记(33)— Go 自定义类型 type(自定义结构体、结构体初始化、结构体内嵌、自定义接口)

    1. 自定义类型格式 用户自定义类型使用关键字 type ,其语法格式是: type newType oldType oldType 可以是自定义类型.预声明类型.未命名类型中的任意一种. newTy ...

  9. 【swift学习笔记】三.使用xib自定义UITableViewCell

    使用xib自定义tableviewCell看一下效果图 1.自定义列 新建一个xib文件 carTblCell,拖放一个UITableViewCell,再拖放一个图片和一个文本框到tableviewc ...

最新文章

  1. 如果要存 IP 地址,用什么数据类型比较好?大部人都会答错!
  2. 2013年下半年信息系统项目管理师考试论文试卷
  3. ubuntu安装node.js
  4. IGDB|2021年大学生夏令营开始报名啦!
  5. 转:PriorityQueue
  6. 初一数学下册电子课本_七年级数学下册人教版-数学七年级下册电子课本-精品下载...
  7. java9 javafx_无法在java 9下针对java 8构建javafx应用程序
  8. cdate在java中_Java Calendar.add方法代码示例
  9. 哪个oracle工具可以免费,Sqlite导入Oracle工具下载官方免费版_SqliteToOracle2.2英文版 - 系统之家...
  10. 如何用一款小工具大大加速MySQL SQL语句优化(附源码)
  11. 外贸常见的付款方式你了解吗?
  12. android无线投屏到电视盒子,【沙发管家】教你如何把电脑视频投屏到智能电视/电视盒子上!...
  13. 主流云协作办公平台竞品分析报告及融合企业自身产品/功能思考
  14. itchat获取群聊用户的信息
  15. 彩色证件照片常用的红色、蓝色背景颜色值
  16. PWM常见输出方法及避坑指南
  17. 第二次网页前端培训笔记(HTML表单标签常用字符实体)
  18. 大厂二面:应对千亿级高并发场景,MySQL如何分库分表?
  19. VSCode快捷键配置复制一行
  20. nftables和iptables的区别

热门文章

  1. 正点原子linux系统移植篇
  2. 给视频配解说词字幕的最便宜方法
  3. 正则表达式_match方法使用
  4. impress.js 源码分析
  5. html边框js特效,JS实现表格的边框闪烁效果代码
  6. 深圳40周年庆祝大会40人,科创界哪些人上榜了?
  7. python身份证号码正则表达式校验(含最后一位的校验值规则)
  8. 考研复习--数据结构
  9. 十分钟学会SSH+SFTP操作终端,告别XShell
  10. android:获取富文本图片和使用Jsoup抓取腾讯新闻网页数据