学习笔记:c++ newdelete关键字及其自定义
文章目录
- 一.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关键字及其自定义相关推荐
- linux添加自己的库,Linux学习笔记——例叙makefile 增加自定义共享库
Linux学习笔记--例说makefile 增加自定义共享库 0.前言 从学习C语言开始就慢慢开始接触makefile,查阅了很多的makefile的资料但总感觉没有真正掌握makefile,如果自己 ...
- ROS 学习笔记(三):自定义服务数据srv+server+client 示例运行
ROS 学习笔记(三):自定义服务数据srv+Server+Client 示例运行 一.自定义服务数据: 1.向功能包添加自定义服务文件(AddTwoInts.srv) cd ~/catkin_ws/ ...
- Polyworks脚本开发学习笔记(十七)-制作宏脚本自定义工具条
Polyworks脚本开发学习笔记(十七)-制作宏脚本自定义工具条 做好的宏脚本程序,每次打开脚本加载程序太多麻烦,为了方便的调用脚本做各种操作,可以使用系统的自定义工具条功能将脚本加载到工具条上. ...
- VSTO 学习笔记(十二)自定义公式与Ribbon
原文:VSTO 学习笔记(十二)自定义公式与Ribbon 这几天工作中在开发一个Excel插件,包含自定义公式,根据条件从数据库中查询结果.这次我们来做一个简单的测试,达到类似的目的. 即在Excel ...
- Dynamic CRM 2013学习笔记(三十三)自定义审批流4 - 规则节点 -有分支的流程处理...
上次介绍过节点的基本配置<Dynamic CRM 2013学习笔记(三十二)自定义审批流3 - 节点及实体配置>,这次介绍下规则节点,因为有时流程里会有一些分支.合并,这时就要用到规则节点 ...
- SpringBoot学习笔记(4):自定义的过滤器
SpringBoot:学习笔记(4)--自定义的过滤器 快速开始 SpringBoot提供的前端控制器无法满足我们产品的需求时,我们需要添加自定义的过滤器. 在SpringBoot的开发中,我们应该还 ...
- 【多线程学习笔记】sychronized关键字底层原理、sychronized与ReentrantLock、volatile和synchronized
文章目录 sychronized释义 synchronized关键字最主要的三种使用方式: synchronized底层原理: 同步代码块: 同步方法 当前类的class对象作为锁 锁升级 Synch ...
- Go 学习笔记(33)— Go 自定义类型 type(自定义结构体、结构体初始化、结构体内嵌、自定义接口)
1. 自定义类型格式 用户自定义类型使用关键字 type ,其语法格式是: type newType oldType oldType 可以是自定义类型.预声明类型.未命名类型中的任意一种. newTy ...
- 【swift学习笔记】三.使用xib自定义UITableViewCell
使用xib自定义tableviewCell看一下效果图 1.自定义列 新建一个xib文件 carTblCell,拖放一个UITableViewCell,再拖放一个图片和一个文本框到tableviewc ...
最新文章
- 如果要存 IP 地址,用什么数据类型比较好?大部人都会答错!
- 2013年下半年信息系统项目管理师考试论文试卷
- ubuntu安装node.js
- IGDB|2021年大学生夏令营开始报名啦!
- 转:PriorityQueue
- 初一数学下册电子课本_七年级数学下册人教版-数学七年级下册电子课本-精品下载...
- java9 javafx_无法在java 9下针对java 8构建javafx应用程序
- cdate在java中_Java Calendar.add方法代码示例
- 哪个oracle工具可以免费,Sqlite导入Oracle工具下载官方免费版_SqliteToOracle2.2英文版 - 系统之家...
- 如何用一款小工具大大加速MySQL SQL语句优化(附源码)
- 外贸常见的付款方式你了解吗?
- android无线投屏到电视盒子,【沙发管家】教你如何把电脑视频投屏到智能电视/电视盒子上!...
- 主流云协作办公平台竞品分析报告及融合企业自身产品/功能思考
- itchat获取群聊用户的信息
- 彩色证件照片常用的红色、蓝色背景颜色值
- PWM常见输出方法及避坑指南
- 第二次网页前端培训笔记(HTML表单标签常用字符实体)
- 大厂二面:应对千亿级高并发场景,MySQL如何分库分表?
- VSCode快捷键配置复制一行
- nftables和iptables的区别