C++(9.5)——浅谈new和delete的实现原理

这篇具有很好参考价值的文章主要介绍了C++(9.5)——浅谈new和delete的实现原理。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

(注:本文是针对上篇文章中C++内存管理的两个关键字)两个关键字原理的解析,对于这两个关键字的使用并没有什么影响,如果只想得知两个关键字的使用方法,则可以直接跳过本篇文章)

目录

1. 引入:

2.operator new 与 operator delete:

2.1 基本定义以及与操作符的差异:

2.2 为什么要引入operator new和operator delete:

3. 操作符的大致动作过程:

3.1 开辟单个空间的动作过程:

3.2 开辟多个空间的动作过程:


1. 引入:

为了方便说明两个关键字的实现原理,首先引入一个简单的栈,具体代码如下:

#include<iostream>
using namespace std;

class Stack
{
public:
	Stack(int capacity = 4)
	{
		cout << "Stack( int capacity = 4)" << endl;
		_a = new int[capacity];
		_capacity = capacity;
		_top = _capacity;
	}

	~Stack()
	{
		cout << "~Stack()" << endl;
		delete[]_a;
		_a = nullptr;
		_top = 0;
		_capacity = 0;
	}
private:
	int* _a;
	int _top;
	int _capacity;
};
int main()
{
	Stack s1;
	return 0;
}

运行代码,结果显示调用了一次构造函数和一次析构函数:

C++(9.5)——浅谈new和delete的实现原理,C++,c++,java,开发语言

对于下方给出的代码,即:

Stack* s2 = new Stack;
	delete s2;

       整体的运行顺序为:利用关键字开辟一个类型为自定义类型的空间,大小为字节。此后,由自定义类型的构造函数可知,再利用关键字为指针变量_开辟空间。因此,第一行代码整体开辟了两次空间。第一次是自身开辟空间,第二次是针对自定义类型会去调用自定义类型的构造函数,在构造函数中,再开辟一次空间。

    对于第二行代码中的关键字。首先需要调用析构函数,析构函数的作用并非像一样释放掉开辟的空间,而是释放掉空间中的资源,也就是指针变量_指向的空间。在调用完析构函数后,再去释放空间。此处可以看出来,针对自定义类型,在释放空间时,并不能区调用。因为并不会处理指针变量_中已经开辟的空间。因此会导致内存泄漏。

    由上面的例子和上篇文章引入关键字使用方法的例子可以了解,针对内置类型与并没有差异,针对自定义类型,比多了一步调用默认构造函数。对于,针对内置类型与也没有差异,针对自定义类型,多了一步在释放空间之前调用一次析构函数。所以,这两个关键字可以看作对的加强。对于这两个关键字开辟空间或者释放空间的功能的原理,是借助,完成的。需要注意,上面给出的是两个全局函数,并非运算符重载。下面将针对这两个全局函数进行解析。

2.operator new 与 operator delete:

2.1 基本定义以及与操作符的差异:

      并不是运算符重载,而是两个全局函数,对于,其运用方式与基本相同,与的调用方式也基本相同。二者与前面的操作符在运行中也有一定的差距,例如:

Stack* s2 = new Stack;
	delete s2;

	Stack* s3 = (Stack*)operator new(sizeof(Stack));
	operator delete(s3);

运行后结果如下:

C++(9.5)——浅谈new和delete的实现原理,C++,c++,java,开发语言

不难发现,两个全局函数只能开辟空间,并不能像操作符一样调用构造函数或者析构函数。

对于这两个全局函数,具体代码如下:
(注:对于下方给出的代码在此阶段并不需要知道具体含义,在文章的后面,需要引用其中某行代码时,会给出相应的解析)

void *__CRTDECL operator new(size_t size) _THROW1(_STD bad_alloc)
{
void *p;
while ((p = malloc(size)) == 0)
     if (_callnewh(size) == 0)
     {
         static const std::bad_alloc nomem;
         _RAISE(nomem);
     }
return (p);
}
void operator delete(void *pUserData)
{
     _CrtMemBlockHeader * pHead;
     RTCCALLBACK(_RTC_Free_hook, (pUserData, 0));
     if (pUserData == NULL)
         return;
     _mlock(_HEAP_LOCK);  
     __TRY
         pHead = pHdr(pUserData);
         _ASSERTE(_BLOCK_TYPE_IS_VALID(pHead->nBlockUse));
         _free_dbg( pUserData, pHead->nBlockUse );
     __FINALLY
         _munlock(_HEAP_LOCK); 
     __END_TRY_FINALLY
     return;
}


#define   free(p)               _free_dbg(p, _NORMAL_BLOCK)

 通过上面给定代码中的其中两行,即:

while ((p = malloc(size)) == 0)
_free_dbg( pUserData, pHead->nBlockUse );

       不难看出,和这两个函数可以看作是对和这两个函数的封装。而对于为什么C++(9.5)——浅谈new和delete的实现原理,C++,c++,java,开发语言要对进行一次封装再使用,而不直接使用,将在下一小节进行简要说明。

2.2 为什么要引入operator new和operator delete:

     若调用开辟空间失败,则一般会返回。但是,在C++(9.5)——浅谈new和delete的实现原理,C++,c++,java,开发语言中,面向对象的编程并不能在失败用返回值进行处理,而是需要抛异常,对进行封装,正是为了解决这个问题

(注:对于抛异常等相关内容将会在后续的文章中给出,在此阶段只需要这个概念即可)

    在上面给出的代码中,虽然具体内容并不能了解清楚,但是对于下面的代码,即:

void *p;
while ((p = malloc(size)) == 0)
     if (_callnewh(size) == 0)
     {
         // report no memory
         // 如果申请内存失败了,这里会抛出bad_alloc 类型异常
         static const std::bad_alloc nomem;
         _RAISE(nomem);
     }

       在介绍时就提到,当成功的开辟空间后,返回值会返回这块空间的起始地址。因此,上述代码的大体意思为:检查的返回值,如果返回值判断等于,则说明没有成功的开辟 地址,下面就进行抛异常。对于的封装大致意思也相同,此处不再过多介绍。

3. 操作符的大致动作过程:

3.1 开辟单个空间的动作过程:

    前面简单介绍了两个全局函数和。本部分将介绍操作符的大致动作过程。

(注:为了清楚的了解的动作过程,需要通过汇编进行查看,本部分并不需要了解汇编代码,只是借用其中的几行来大体说明动作过程,并且针对借用的代码给出解析)

   对于下面给出的代码:

Stack* s2 = new Stack;

转为汇编形式,即为:

C++(9.5)——浅谈new和delete的实现原理,C++,c++,java,开发语言

在上面的指令中,可以找到较为熟悉的两行指令,即:

C++(9.5)——浅谈new和delete的实现原理,C++,c++,java,开发语言

       二者分别对应了操作符的两个动作,即:调用函数开辟空间,调用构造函数对空间进行初始化。 对于操作符同理,其汇编指令如下:

C++(9.5)——浅谈new和delete的实现原理,C++,c++,java,开发语言

其中,红色框框出来的两行分别为:调用析构函数与调用释放空间。 

3.2 开辟多个空间的动作过程:

给定代码如下:

Stack* s4 = new Stack[10];
	delete[]s4;

将上述代码转为汇编形式,涉及到的指令如下:
C++(9.5)——浅谈new和delete的实现原理,C++,c++,java,开发语言

C++(9.5)——浅谈new和delete的实现原理,C++,c++,java,开发语言

        可以看到,大致的运行过程是先调用指令,下一步直接会转到。其中的表示开辟空间的大小。
 文章来源地址https://www.toymoban.com/news/detail-799242.html

到了这里,关于C++(9.5)——浅谈new和delete的实现原理的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • C++:new 和 delete

    个人主页 : 个人主页 个人专栏 : 《数据结构》 《C语言》《C++》 本篇博客作为C++:new 和 detele操作符的知识总结 注意:申请连续空间初始化时与数组初始化类似 注意:申请和释放单个元素空间,使用new 和 delete操作符,申请和释放连续的空间,使用new[] 和 delete[]。 注意:

    2024年02月07日
    浏览(36)
  • C++ :内存管理 new&delete

    目录 内存区域划分 C++的动态内存的管理方式   new new的基本使用方法  【注意事项】  delete  【注意】 new和delete操作自定义类型  operator new 和 operator delete  【关于自定义类型new申请内存】 【原理】  【调用顺序】  【连续开辟空间问题】  malloc/free和new/delete的区别 【说明

    2024年02月22日
    浏览(45)
  • C++ new和delete详解

    说明: 栈又叫堆栈–非静态局部变量/函数参数/返回值等等,栈是向下增长的 内存映射段是高效的I/O映射方式,用于装载一个共享的动态内存库。用户可使用系统接口创建共享共享内存,做进程间通信。(Linux课程如果没学到这块,现在只需要了解一下) 堆用于程序运行时动

    2024年02月09日
    浏览(38)
  • C++ new/delete的使用

    1.虚拟地址空间 可执行程序(进程)的虚拟地址空间: 内核:操作系统 栈区:函数的形参,非静态的局部变量,函数现场保护数据等等,栈是向下增长的,栈顶是低地址,栈底是高地址,存储结构为“先进后出”,栈区是一块连续的内存区域。 共享库的内存映射区域:用于

    2024年02月15日
    浏览(32)
  • C++内存管理(new和delete)

    目录 1. new/delete操作内置类型 2. new和delete操作自定义类型 3. operator new与operator delete函数  4 .new和delete的实现原理 1 .内置类型 2 .自定义类型 new的原理 delete的原理 new T[N]的原理 delete[]的原理 5. 定位new表达式(placement-new) 6. malloc/free和new/delete的区别 7.内存泄漏 内存泄漏分类 8.如

    2024年02月02日
    浏览(39)
  • 【C++】——内存管理(new和delete)

    在学习C语言的时候,我们学习了动态内存管理,也就是在堆上动态开辟一些内存供我们使用,虽然C语言内存管理的方法在C++中也可以使用,但还有一些地方是他无能为力的,所以我们今天来学习C++内存管理的方式。 在学习内存管理之前,我们先来认识一下C/C++中程序内存区

    2024年02月06日
    浏览(54)
  • 【C++】内存管理(new与delete)

    👀 樊梓慕: 个人主页  🎥 个人专栏: 《C语言》《数据结构》《蓝桥杯试题》《LeetCode刷题笔记》《实训项目》《C++》 🌝 每一个不曾起舞的日子,都是对生命的辜负 本篇文章我们一起来学习C++的内存管理方式,实际上C++与C语言的内存管理模式是十分相似的,他们的内存

    2024年02月05日
    浏览(45)
  • C++ new和delete的使用

    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 new和delete是C++里非常重要的两个,意味着从“自由存储(堆)”分配指定大小的内存和释放掉这些内存。这些用法哪怕初学者也会,但是今天要讲的不是这个。今天要讲的是使用中容易忽视的细节

    2024年02月09日
    浏览(49)
  • C++内存管理(2)new、delete详解

    目录 new operator(new操作) new类对象时加不加括号的差别 new工作任务 delete工作任务 new和delete 堆区空间操作(对比malloc和free) new和delete操作基本类型的空间 new和delete操作基本类型的数组 new和delete操作类的空间 new和delete操作对象数组 new内存分配细节探秘 为什么要尽可能少的

    2024年02月09日
    浏览(51)
  • C++如何进行内存管理 (new、delete)

    我成功是因为我有决心,从不踌躇。——拿破仑  本章是关于c++内存管理的文章,字数不多,内容简单,希望对你有所帮助!! 话不多说安全带系好,发车啦 (建议电脑观看) 。 附:红色,部分为重点部分;蓝颜色为需要记忆的部分(不是死记硬背哈,多敲);黑色加粗或

    2024年02月08日
    浏览(102)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包