「C++」new 和 delete

本文详细阐述了C++中内存区域划分,new、delete操作符的使用,以及它们与内置和自定义类型内存分配的关系,涉及构造函数和析构函数。还揭示了operatornew和operatordelete的底层实现原理。
摘要由CSDN通过智能技术生成


前言

在C语言中我们使用malloc、realloc、calloc来动态开辟内存空间,虽然在C++里面也能使用它们,但因为C++新增了需要C语言所没有的特性,使得C语言老的那套已经不再适合C++。


一、内存区域划分

在介绍C++的新机制前,我们先来了解一下C++内存的区域划分。

  • :用于存放局部变量,数据由高位向低位增长,数据的释放由编译器来控制。
  • 内存映射段:高效的 I/O 映射方式,用于装载一个共享的动态内存库,创建共享内存,做进程间通信。
  • :用于存放动态开辟的内存,数据由低位地址向高位地址上升,开辟的空间需要手动释放。
  • 数据段:用于存放已经初始化的全局变量和静态变量。
  • 代码段:存放可执行的代码/只读常量。
    在这里插入图片描述

二、new 与 delete

为了适应C++的类和异常机制,C++新增了两个新的操作符,newdelete,它们和C语言开辟空间的方式类似,必须手动开辟,手动释放。

  • new:用于动态开辟内存空间。
  • delete:用于删除开辟的内存。

开辟内置数据类型

int main()
{
	// 动态开辟一个int类型的空间
	int* p1 = new int;
	// 动态开辟一个int类型的空间并初始化为10
	int* p2 = new int(5);
	//动态开辟一个10个int类型的空间
	int* p3 = new int[10];
	
	// 必要自己手动释放空间
	delete p1;
	delete p2;
	delete[] p3;
	
	return 0;
}

注意:new和delete要配套使用,申请连续的空间时,必须使用带 [ ] 的 new 与 delete。

开辟自定义类型

new 在开辟类的空间时,必定会调用其构造函数, 而 delete 时会调用其析构函数,但C语言中的 mallocfree 函数并不会调用。

class A
{
public:
	A(int a = 0) : _a(a) {cout << "A()" << endl; }
	~A() { cout << "~A()" << endl; }
private:
	int _a;
};

int main() {
	A* aa = new aa[10];
	A* a2 = (A*)malloc(sizeof(A) * 10);

	delete [] aa;
	free(a2);
}

结果可得知:A()被调用了10次,~A()被调用了10次

二、operator new 与operator delete函数

虽然new 与 delete它们是操作符,但在使用时还是调用了全局函数,现在让我们深入它们的内部,了解它们是如何工作的吧。

operator new

new 在使用时调用的全局函数operator new来动态开辟空间

 void *__CRTDECL operator new(size_t size) _THROW1(_STD bad_alloc)
 {
	 // try to allocate size bytes
	 void *p;
	 // 使用malloc申请size字节空间
	 while ((p = malloc(size)) == 0)
		if (_callnewh(size) == 0)
	     {
	     	// 如果申请失败抛出异常
			static const std::bad_alloc nomem;
		 	_RAISE(nomem);
	    }
	 return (p);
 }

从这里我们可以看出来,其实new 不只是为了类服务的,同时还为了C++的异常服务。

operator delete

delete 也是一样调用了对应的operator delete 全局函数来释放空间。

 void operator delete(void *pUserData)
 {
	 _CrtMemBlockHeader * pHead;
	 
	 RTCCALLBACK(_RTC_Free_hook, (pUserData, 0));
	 
	 if (pUserData == NULL)
	 	return;
	 _mlock(_HEAP_LOCK);  /* block other threads */
	 __TRY
	 
		 /* get a pointer to memory block header */
		 pHead = pHdr(pUserData);
		 
		 /* verify block type */
		 _ASSERTE(_BLOCK_TYPE_IS_VALID(pHead->nBlockUse));
		 
		 _free_dbg( pUserData, pHead->nBlockUse );
		 
	 __FINALLY
	 _munlock(_HEAP_LOCK);  /* release other threads */
	 __END_TRY_FINALLY
	 
	 return;
 }
 /*
 free的实现
*/
 #define   free(p)               _free_dbg(p, _NORMAL_BLOCK)

我们最终可以发现 new 与 delete 的内部设计也时用 malloc 与 free 来实现的

new 与 delete 的实现原理

在申请内置类型的时候,malloc/free 与 new/delete 之间没有太大区别,但 new/delete 在申请连续空间时需要使用 [ ] ,而且在开辟失败时会抛出异常。

new 的原理

  • new 的原理
    1. 调用operator new函数申请空间
    2. 在申请的空间上执行构造函数,完成对象的构造
  • new T[N] 的原理
    1. 调用operator new[]函数申请空间,完成N个对象空间的申请
    2. 在申请的空间上执行N次构造函数

delete 的原理

  • delete 的原理
    1. 先执行析构函数,完成对象中资源的清理
    2. 调用operator delete函数释放空间
  • delete[]的原理
    1. 在释放的对象空间上执行N次析构函数,完成N个对象资源的清理
    2. 调用operator delete[]来释放空间。

总结

性质是否抛出异常是否调用析构/构造
malloc函数
new操作符
free函数
delete操作符
  • 8
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值