C++内存管理(区别C语言)深度对比

avatar
作者
筋斗云
阅读量:0

欢迎来到我的Blog,点击关注哦💕

前言

前面已经介绍了类和对象,对C++面向对象编程已经有了全面认识,接下来要学习对语言学习比较重要的是对内存的管理。

一、内存的分区

  1. 代码区:存放程序的机器指令,通常是可共享的,并且通常为只读的,以防止程序意外修改自身的代码。
  2. 全局/静态存储区:存放全局变量和静态变量,这些变量在程序的整个生命周期内都存在。
  3. 堆区:用于动态分配内存,程序运行时根据需要通过malloc、calloc、realloc等函数在堆区中分配内存空间。
  4. 栈区:存放函数的局部变量和函数调用的参数,由编译器自动管理,遵循后进先出的原则。
  5. 常量区:存放常量数据,如字符串字面量,这些数据在程序运行期间不可修改。
  6. 代码区:存放程序的二进制代码,是程序执行指令的存储空间。

在这里插入图片描述

二、C语言中的内存管理(参考

  • malloc函数用于动态分配指定大小的内存空间,并返回指向该内存的指针。如果分配成功,返回非NULL指针;否则返回NULL。
  • calloc函数除了分配内存外,还会将分配的内存初始化为零。
  • realloc函数用于调整已分配内存的大小,可能会移动内存块以适应新的大小要求。
  • free函数用于释放之前通过动态内存分配函数分配的内存空间

三、C++中的内存管理

C++内存分配

不同于C语言,C++有着自己独立动态内存开辟的方法:

​ 主要通过newdelete操作符来实现new操作符用于分配单个对象或数组,而deletedelete[]分别用于释放这些对象或数组所占用的内存.

下面是new和delete应用的实例:

 //动态申请一个int大小空间 int* p0 = new int; //动态申请一个int大小空间并且初始化为0 int* p1 = new int (0); //动态申请10个int大小空间 int* p2 = new int[10]; //动态申请10个int大小空间并且初始化为0 int* p3 = new int[10] {0};  delete p0; delete p1; delete[] p2; delete[] p3;  

注意

  1. 不要使用delete释放非new开辟的空间
  2. 不要使用delete释放同一块空间两次
  3. 如果使用new [ ] 开辟数组进行内存分配,应该使用delete [ ] 来释放
  4. 如果new对一个实体进行内存分配,应该使用delete(没有方括号)进行释放

四、new 和 delete深度探索

有关operator new 和operator delete

operator new

  • operator new是一个特殊的操作符,用于动态分配内存。它与new操作符密切相关,但它们在语义上有所区分。

  • new操作符是一个高级操作符,它不仅分配内存,还自动调用对象的构造函数。

  • operator new仅负责分配内存,不涉及对象的构造。

  • operator new可以被重载,以便为特定的类或全局范围提供自定义的内存分配策略

  • operator new:该函数实际通过``malloc来申请空间,当malloc`申请空间成功时直接返回

  • 申请空间失败, 尝试执行空 间不足应对措施,如果改应对措施用户设置了,则继续申请,否则抛异常。

通俗的讲 ,new 不仅仅可以进行空间开辟,针对自定义类型会调用其构造函数,而new也是调用重载(operator new),进行内存的分配,然而 operator new 进行内存分配是通过malloc进行实现的,这正是区别于C语言的其中一点。

关于时间类和汇编语言:

class Date { public: 	Date(int year = 1,int month = 1,int day = 1) 		:_year(year) 		,_month(month) 		,_day(day) 	{} 	~Date() 	{ 		_year = 0; 		_month = 0; 		_day = 0; 	}  private: 	int _year = 1; 	int _month = 1; 	int _day = 1; };  	Date* d1 = new Date; 00007FF62A0D19FC  mov         ecx,0Ch   00007FF62A0D1A01  call        operator new (07FF62A0D103Ch)//调用operator new内存分配 00007FF62A0D1A06  mov         qword ptr [rbp+108h],rax   00007FF62A0D1A0D  cmp         qword ptr [rbp+108h],0   00007FF62A0D1A15  je          main+5Dh (07FF62A0D1A3Dh)   00007FF62A0D1A17  mov         r9d,1   00007FF62A0D1A1D  mov         r8d,1   00007FF62A0D1A23  mov         edx,1   00007FF62A0D1A28  mov         rcx,qword ptr [rbp+108h]   00007FF62A0D1A2F  call        Date::Date (07FF62A0D13D4h)    // 调用构造函数 00007FF62A0D1A34  mov         qword ptr [rbp+118h],rax   00007FF62A0D1A3B  jmp         main+68h (07FF62A0D1A48h)   00007FF62A0D1A3D  mov         qword ptr [rbp+118h],0   00007FF62A0D1A48  mov         rax,qword ptr [rbp+118h]   00007FF62A0D1A4F  mov         qword ptr [rbp+0E8h],rax   00007FF62A0D1A56  mov         rax,qword ptr [rbp+0E8h]   00007FF62A0D1A5D  mov         qword ptr [d1],rax  

operator delete

  • operator delete 是一个全局函数,用于释放之前通过 operator new 分配的内存。
  • 它是 new 操作符的逆运算,负责在内存释放时执行必要的清理工作。
  • operator delete 通常在 delete 表达式中被隐式调用,用于释放单个对象或对象数组的内存
  • 在空间上执行析构函数,完成对象中资源的清理工作
  • 调用operator delete函数释放对象的空间(通过free)
00B72150	push	ebp	已用时间<=1ms	 00B72151	mov	ebp,esp	 00B72153	sub	esp,0cCh	 00B72159	push	ebx	 00B7215A	push	esi	 00B7215B	push	edi	 00B7215C	push	ecx	 00B7215D	lea	edi,[ebp-0Ch]	 00B72160	mov	ecx,3	 00B72165	mov	eax,0cccccccch	 00B7216A	rep stos	dword ptr es:[edi]	 00B7216C	pop	ecx	 00B7216D	mov	dword ptr [this],ecx	 00B72170	mov	ecx,dword ptr [this]	 00B72173	call	A::~A (0B7154Bh)			//调用析构函数 00B72178	mov	eax,dword ptr [ebp+8]	 00B7217B	and	eax,1	 00B7217E	je	__call_empty_init_list_helper<A>+0Eh (0	 00B72180	push	4	 00B72182	mov	eax,dword ptr [t.	ebp	15990024	 00B72185	push	eax	 00B72186	call	operator delete (0B710AAh)	//释放空间 00B7218B	add	esp,8	 00B7218E	mov	eax,dword ptr [this]	 00B72191	pop	edi	 00B72192	pop	esi                                                          

小结

new 和delete 调用的时候内部调用的顺序

  • new 先进行空间的开辟(malloc),在进行对象的实例化
  • delete先进行析构函数的调用,进行资源的销毁,在进行空间的释放(free
newoperatornew构造函数delete析构函数operatordelete

五、replacement new

在C++中new操作符通常用于在堆上分配内存并调用对象的构造函数。除了常规的new操作符外,C++还提供了operator newplacement new两种替代机制。operator newnew操作符内部使用的函数,可以被重载以提供自定义的内存分配策略。而placement new是一种特殊的new表达式,它允许在已分配的内存上构造对象,而不是分配新的内存。

//用法 new(place_address)type 

应用场景:

池化技术:

化技术在C++编程中通常指的是预先分配一定数量的资源(如内存、线程等)并存储在一个“池”中,以便在程序运行时可以快速地从中获取和返回资源,而不是每次都进行昂贵的动态分配和释放操作。

这个就是进行已有空间进行对象实例化

六、C语言和C++内存分配的区别

区别mallocfreenewdelete

  1. mallocfree是函数,而newdelete是操作符
  2. malloc不可以初始化而new可以初始化
  3. malloc进行内存分配的时候是手动计算空间的大小,而new后面跟类型,大小在 [ ]中指定
  4. malloc的返回值为void*, 在使用时必须强转,new不需要,因为new后跟的是空间的类型
  5. malloc申请空间失败是返回NULL,而new申请空间失败是捕获异常
  6. 申请自定义类型对象时,malloc/free只会开辟空间,不会调用构造函数与析构函数,而new在申请空间 后会调用构造函数完成对象的初始化,delete在释放空间前会调用析构函数完成空间中资源的清理

void*, 在使用时必须强转,new不需要,因为new后跟的是空间的类型
5. malloc申请空间失败是返回NULL,而new申请空间失败是捕获异常
6. 申请自定义类型对象时,malloc/free只会开辟空间,不会调用构造函数与析构函数,而new在申请空间 后会调用构造函数完成对象的初始化,delete在释放空间前会调用析构函数完成空间中资源的清理

广告一刻

为您即时展示最新活动产品广告消息,让您随时掌握产品活动新动态!