C++入门基础(九) new & delete

28 篇文章 0 订阅
9 篇文章 0 订阅

前言

  在内存的应用中,我们继续深入展开。内存是如何开辟的?我们知道在编写程序之后,编译器会自动的给变量、常量数据、静态数据等给予对应的内存空间作为储存,而当我们的程序稍微复杂一点,需要进行有意识的根据不同场景开辟不同大小的空间去使用,该如何实现呢?因此在这里我们有一个概念叫做空间的动态开辟,在C语言中我们会使用malloccalloc或者realloc去进行一定大小空间的开辟,使用free在最后对开辟的空间进行释放。这些方式在C++中同样适用,但是在有一些特殊的地方使用起来往往比较麻烦有时甚至无法使用(比如在对自定义类型使用时无法调用构造函数与析构函数,从而造成随机值产生以及内存泄漏情况),因此C++便提出了属于自己的内存管理方式,通过new和delete操作符进行动态内存的管理。
  通俗的意义上来说,new表示申请一段空间,delete表示释放一段空间,两者成对出现。

new使用方法

操作内置类类型

1.动态申请一个数据类型的空间

数据类型* + 指针变量名称 = new +变量类型

int* a = new int;//申请一个int型数据大小的空间

2.动态申请一个指定数据类型的空间并初始化

数据类型* + 指针变量名称= new +变量类型(val)

int* b = new int(20);//申请一个int型数据大小的空间,并附初始值为20

3.动态申请若干个指定数据类型的空间

数据类型* + 指针变量名称 = new +变量类型[number]

int* c = new int[10];//申请10个int型数据大小的空间,初始值为随机值

【注意】使用new时,()表示开辟完后设置初始值,[]表示开辟若干数量个空间,二者不可以同时使用

操作自定义类型

1.申请单个自定义类型的空间

类型名* +指针变量名=new 类型名

Class_name* p1=new Class_name;

2.申请多个自定义类型的空间

类型名* +指针变量名=new 类型名[number]

Class_name* p1=new Class_name[n];

delete使用方法

1.释放单个的空间

delete + 指针变量名称

delete a;

2.释放连续的空间

delete+[]+指针变量名称

delete[] c;

【注意】new在delete使用时成对出现,molloc、realloc以及calloc与free搭配使用,new与delete搭配使用,不能混合使用。

malloc与new的主要区别

  1. malloc是申请空间的函数,free是操作符
  2. malloc只是申请一部分空间,不对空间做任何处理,new申请空间的同时进行初始化
  3. malloc申请空间需指定字节大小,new会根据类型自动计算
  4. malloc申请的空间需要制定类型,因为其返回值是void*,new不需要,其返回值类型就是类型指针
  5. malloc申请失败返回NULL,需要手动判断是否开辟成功,new申请失败会捕捉异常
  6. 在对自定义类型进行申请时,malloc与free只会开辟空间不会调用构造函数与析构函数,因此并不会进行初始化,同时free只会释放空间不会对资源进行清理,而new会对对象进行初始化,delete在释放空间时同时对资源进行清理。
  7. new进行连续申请时,若没有默认构造函数则无法进行。

代码如下,进行对比:

#include<iostream>
using namespace std;
class Grade
{
public:
	Grade(int math = 60, int chinese = 60, int english = 60)
		:_Math(math),
		_Chinese(chinese),
		_English(english)
	{}
private:
	int _Math;
	int _Chinese;
	int _English;

};

int main()
{
	Grade St(90,90,90);//对象实例化
	Grade* st1 = new Grade;//构建单个对象,观察是否调动构造函数
	Grade* st2 = new Grade(10, 20, 30);//构建初始化对象
	Grade* st3 = (Grade*)malloc(sizeof(Grade));//使用malloc,观察是否调用构造函数
	Grade* arr_st = new Grade[10];//构造多个对象
	Grade* arr_st1 = (Grade*)malloc(sizeof(Grade)*10);//使用malloc构造多个对象
	//观察是否调用析构函数
	delete st1;
	delete st2;
	free(st3);
	delete[] arr_st;
	free(arr_st1);
	cout << "end" << endl;
	return 0;


}

在这里插入图片描述

operator new和operator delete

  首先要清楚,operator new和operator delete并不是运算符的重载,而是系统提供的全局函数,new在底层调用operator new全局函数来申请空间,delete在底层通过operator delete全局函数来释放空间。在底层,它们党的使用方式类似于malloc和free。

例如需要申请一个整型的空间,以及其对应释放

int* pq=(int*)operator new(sizeof(int));
operator delete(pq);

  下面我们来观察一下其源码如下:

//operator new 的代码实现
void *__CRTDECL operator new(size_t size) _THROW1(_STD bad_alloc)
{
	// try to allocate size bytes
	void *p;
	while ((p = malloc(size)) == 0)
	if (_callnewh(size) == 0)
	{
		// report no memory
		//如果申请失败则抛出错误
		static const std::bad_alloc nomem;
		_RAISE(nomem);
	}
	return (p);
}
//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;
}

  由此我们可以看出operator new实际上依旧是通过malloc来申请空间,如果不成功,则抛出相对应的错误,并且执行相关用户提供的措施,而operator delete最后还是通过free来进行空间的释放,只是其中的过程更加详细。
  所以我们可以知道new与delete实际上的工作原理其实并不复杂,在内置类型的申请(释放)上new(delete)和malloc(free)是一样的,只不过,new在失败时会抛出异常;而在进行自定义类型空间申请(释放)时,会调用operator new(operator delete)函数,之后在执行构造函数(析构函数)

欢迎大家批评指正,共同进步。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值