C++ 内存基本构件new/delete的意义、运用方式以及重载方式
目录
- 一、对new的理解
- 1、new做了什么
- 2、new被编译器转为了什么
- 3、operate_new源代码长啥样
- 二、对delete的理解
- 1、delete做了什么
- 2、delete被编译器转为了什么
- 3、operator delete源代码长啥样
- 三、构造函数与析构函数的直接调用
- 参考
一、对new的理解
1、new做了什么
C++告诉我们,new的时候会分配一块内存用来放对象,分配好之后会调用构造函数。所以说所谓的自动调用,其实是被new调用的。
所以总结new做的动作:1、分配内存 2、调用构造函数
2、new被编译器转为了什么
以下面语句为例:
Complex* pc = new Complex(1,2);
仿造编译器的流程,可以具化为:
try{//1、allocatevoid* mem = operate_new(sizeof(Complex));//2、cast,将指针转型为Complex*类型指针pc = static_cast<Complex*>(mem);//3、construct,注意这种写法只有编译器才能使用,我们需要避免这种行为pc->Complex::Complex(1,2);
}
catch(std::bad_alloc){//若allocation失败就不执行构造函数
}
注意第3点,如果想要直接调用ctor,可以使用placement new:
new(p)Complex(1,2);
3、operate_new源代码长啥样
这里截取的是vc98版本的源代码:
可见,如果分配内存成功,就返回分配到的内存的指针,否则陷入while循环中。
什么时候会失败?大量耗用内存之后,我们需要new一个对象,会发现我们调用不到内存了。
这时会使用callnewh函数,即调用newhandle函数,这是一种自设定的函数。也就是说,分配内存失败就会调用你设定的那个函数。我们需要在newhandle函数中释放内存,以便调用完newhandle函数后会有内存给malloc分配。
关于函数的第二个参数
nothrow与异常的抛出有关,它是不抛异常,意思是说operate_new这个函数是保证不抛异常的,在新版的C++特性中,不抛异常的写法有做修改。
它的解释如下:
struct std::nothrow_t {};
The struct is used as a function parameter to operator new to indicate that the function should return a null pointer to report an
allocation failure, rather than throw an exception.
二、对delete的理解
1、delete做了什么
C++告诉我们,delete的时候会先调用析构函数,然后调用delete函数释放内存。
2、delete被编译器转为了什么
先调用delete函数:
Complex* pc = new Complex(1,2);
...
delete pc;
被编译器转为:
pc->~Complex(); //先析构,注意这里可以直接调用析构函数
operator delete(pc); //然后释放内存
3、operator delete源代码长啥样
也就是直接调用free函数。
总结一下,new与delete调用的是operate_new和operator delete。而operate_new调用的是malloc函数,operator delete调用的是free函数。
三、构造函数与析构函数的直接调用
先通过指针调用构造函数,这里先选择string类,因为string在标准库里面是个typedefine,本名为basic_string。编译器把第一个string换成了basic_string,后面再找string没有找到,所以这里会报错。这个并不是真正不能使用构造函数的原因。
例1:
string* pstr = new string;cout << "str= " << *pstr << endl;//! pstr->string::string("jjhou"); //[Error] 'class std::basic_string<char>' has no member named 'string'
//! pstr->~string(); //crash -- 其語法語意都是正確的, crash 只因為上一行被 remark 起來嘛. cout << "str= " << *pstr << endl;
例2:
可以看到在GCC里面通过指针或者直接调用构造函数是不正确的,在VC中,条件会放宽。
class A
{public:int id;A() : id(0) { cout << "default ctor. this=" << this << " id=" << id << endl; }A(int i) : id(i) { cout << "ctor. this=" << this << " id=" << id << endl; }~A() { cout << "dtor. this=" << this << " id=" << id << endl; }
};A* pA = new A(1); //ctor. this=000307A8 id=1cout << pA->id << endl; //1
//! pA->A::A(3); //in VC6 : ctor. this=000307A8 id=3//in GCC : [Error] cannot call constructor 'jj02::A::A' directly//! A::A(5); //in VC6 : ctor. this=0013FF60 id=5// dtor. this=0013FF60 //in GCC : [Error] cannot call constructor 'jj02::A::A' directly// [Note] for a function-style cast, remove the redundant '::A'cout << pA->id << endl; //in VC6 : 3//in GCC : 1 delete pA; //dtor. this=000307A8
参考
https://www.bilibili.com/video/BV1Kb411B7N8?p=7
C++ 内存基本构件new/delete的意义、运用方式以及重载方式相关推荐
- C++ 内存基本构件new [] /delete []的意义、内存泄漏原因、VC下cookie的基本布局
目录 一.对new [] delete [] 的理解 1.delete的[]遗漏会带来什么影响 二.以示例探讨 三.cookie的理解 一.对new [] delete [] 的理解 new的对象是个 ...
- 动态内存管理 new 和 delete
动态内存管理 new 和 delete 在软件开发中,需要动态地申请和销毁内存空间.在C语言中是提供了库函数malloc()和free()来分配和撤销内存空间的.但是,使用malloc()函数时必须指 ...
- operator new/delete,operator-> / *【C++运算符重载】
operator new/delete 预定义的内存 operator new/delete 语法格式 举例说明 operator new/delete 预定义的内存 适用于极个别情况需要定制的时候才 ...
- C++ 动态内存管理:c/c++的动态内存管理,new/delete,operator new/delete,placement-new, 内存泄漏
c/c++的动态内存管理 new/delete opeartor new/delete placement-new 内存泄漏 c/c++的动态内存管理 在开始之前首先要了解c和c++的内存分布,我简单 ...
- C++ 内存基本构件 placement new
用法以及编译器解释 placement new 允许我们将object构建于已经分配的内存上.(所以此时必须有个指针指向已经分配好的内存) 没有所谓的placement delete ,因为place ...
- 【C++】 内存空间布局、new/delete、malloc/free
内存空间的布局 每个应用都有自己独立的内存空间,其内存空间一般都有以下几大区域 栈空间 每调用一个函数就会自动分配一段连续的栈空间来存储函数产生的局部变量,等函数调用完毕后会自动回收 自动分配和回收 ...
- oracle导数据不释放内存,关于ORACLE数据库delete后释放空间问题
前些天给一家客户开发个接口,还原了正式数据库,由于数据库存储量太大,还原后基本没什么空间了,有个业务表使用频繁,决定删除前期数据,只留近两个月数据以便测试. 数据量太大,等待时间长,就分段删除的,删了 ...
- c++内存管理:new与delete,深拷贝与浅拷贝
目录 new和delete: 深拷贝与浅拷贝: 引用计数类与写实拷贝: new operator.newoperaot与定位new: new和delete: new会返回申请空间的指针. 以下代码段等 ...
- 查看主机内各组件参数——Cpu、内存、显卡、主板、硬盘(不拆主机方式)
假设你不知道你的主机内部的各项组件数据,请拆开你的主机箱,将内部的所有组件拆开,并且依序列出: cpu的厂牌.型号.最高频率: 内存的容量.接口(DDR/DDR II 等): 显卡的接口(AGP /P ...
最新文章
- Debussy的安装
- 玩转不同业务场景,这些RabbitMQ特性会是得力助攻
- 皮一皮:谁没有年少轻狂过...
- ObjectInputStreamObjectOutputStream工具类
- 如何才能在SQL查询器中使用语句查询出表的列名及数据类型(包括类型和长度)...
- linux添加svn分支,TortoiseSVN 分支创建与合并
- 南京oracle soa,Oracle SOA平台之甲骨文SOA套件概述
- 小姐姐公开征婚高智商 IT 男:微信号竟要质数解密?
- guava 集合上 三
- U3D游戏包il2cpp逆向解包,apk加密资源解密
- 华为S2000系列交换机电源维修
- 超好用的在线思维导图网站
- C# 读取写入Json文件
- 杭州最新公交线路一览(41-50)
- 中国电信CTWAP和CTNET已经融合
- 生成时间序列每月月初月末
- Binomial Heap
- python公约数公倍数_python 公倍数,公约数问题
- LocalDate日期操作与处理
- 计算机语言 帕斯卡,用帕斯卡语言编程
热门文章
- roads 构筑极致用户体验_长安马自达「悦马星空」计划上线,为用户带来极致服务体验...
- 北邮计算机系统结构课件,TEC-8 运算器组成实验(北邮).ppt
- mysql构建栋_【转载】这次拆库 应是微服务化的拆分方式
- Npm install failed with “cannot run in wd”
- CSS实现垂直居中的方法
- django中间件及中间件实现的登录验证
- async,await
- npm git 遇到的问题解决笔记
- NOIP2017年11月9日赛前模拟
- javascript数据结构-栈