C++内存管理(二)---new和delete详解

12 篇文章 0 订阅

C++内存管理方式

接C++内存管理(一)来继续阐述

new/delete操作内置类型
int main()
{
	int* ptr1 = new int;//动态申请一个int大小的空间
	int* ptr2 = new int(5);
	//将ptr2指针所指向的空间中的值初始化为5
	int* ptr3 = new int[4];//动态申请连续的4个int大小的空间

	ptr3[1] = 1;//可以正常使用进行解引用等
	ptr3[2] = 2;
	//当然也要进行释放
	delete ptr1;
	delete ptr2;
	delete[] ptr3; //连续的空间需要加上[]进行释放
	return 0;
}
  • 指针ptr1在堆上申请了一个int大小的空间
  • 指针ptr2在堆上申请了一个int大小的空间,并且将空间中的值置为5
  • 指针ptr3在堆上申请了连续的4个int大小的空间,并且用ptr3指向该空间头部
  • delete 进行空间的释放,ptr1、ptr2直接进行释放即可,但是,ptr3由于是连续多个int空间,所以释放时候需要使用delete[]来进行释放
    注意:new/delete是两个操作符,不同于C语言中的malloc/free,malloc/free为函数,而new/delete为操作符
new/delete操作自定义类型
动态申请单个自定义类型空间

首先,定义一个自定义类型Test类

class Test
{
public:
	Test()
		:data(10)
	{
		cout << "Test()" << this << endl;
	}
	Test(int _data)
		:data(10)
	{
		cout << "Test()" << this << endl;
	}

	~Test()
	{
		cout << "~Test()" << this << endl;
	}
private:
	int data;
};

//进行new与delete的测试
int main()
{
	Test* iptr1 = new Test; //调用默认的构造函数,如果用户显式给出,则没有默认构造,则会出错
	Test* iptr2 = new Test(10); //调用带有参数的构造函数
	delete iptr1, iptr2;
	return 0;
}
  • 如果类中没有给出构造函数, 则new时只能使用第一种方式,new Test后不带有括号括号是传递参数的,默认的构造函数是无参的
  • 如果类中显式定义了构造函数,则类中将不存在默认的构造函数,所以,new在调用时,只能调用类中给出的构造函数的参数类型。必须使用new Test(参数)进行new申请
    在这里插入图片描述
动态申请连续的自定义类型空间
int main()
{
	Test* ptr = new Test[10];
	delete[] ptr;
	return 0;
}
  • 申请连续的自定义类型空间new Test[10],用delete[] ptr来进行回收。申请了十个空间,所以调用构造函数10次,释放10个空间所以调用析构函数10次
    在这里插入图片描述
operator new与operator delete函数
库文件中的operator new 与 operator delete**

operator new:该函数实际通过malloc来申请空间,当malloc申请空间成功时直接返回;申请空间失败,尝试执行空间不足应对措施,如果改应对措施用户设置了,则继续申请,否则抛异常。
operator delete:该函数最终是通过free来释放空间的。、

👇下面是operator new 与operator delete 的源码:可供参考

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            
		// 如果申请内存失败了,这里会抛出bad_alloc 类型异常            
		static const std::bad_alloc nomem;           
		_RAISE(nomem);        
	}
	return (p);
}

/* operator delete: 该函数最终是通过free来释放空间的 */ 
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;
}
  • 通过上述的源码我们可以了解到, new 与 delete 底层都是使用的malloc与free来进行申请与释放空间的,并且对于空间的把控更为严谨加入了抛出 / 捕获异常机制
  • 如果C语言中,malloc申请空间失败,则会返回一个NULL指针
operator new[ ] 源码
// newaop -- operator new[](size_t) REPLACEABLE
#include <new>

void *__CRTDECL operator new[](size_t count) _THROW1(std::bad_alloc)
	{	// try to allocate count bytes for an array
	return (operator new(count));
	}

/*
 * Copyright (c) 1992-2007 by P.J. Plauger.  ALL RIGHTS RESERVED.
 * Consult your license regarding permissions and restrictions.
 V5.03:0009 */

我们可以看出,operator new[ ]在底层调用的是operator new来进行申请空间的。

new/delete实现原理
对于内置类型

对于内置类型,C++可以知道该内置类型的大小,所以,new 会调用operator new(operator new 会调用 malloc)来进行申请内置类型大小的空间。
delete 也会相应的直接调用free来释放对应的空间。

对于自定义类型
new / delete

对于自定义类型的空间申请,由于new不清楚内置类型空间的大小, 所以在使用new申请空间时,需要先对于自定义类型的构造,然后再在堆上申请相应的空间大小。
delete 先在相应对象上执行析构函数,然后再完成对象的资源清理。

new[ ] / delete[ ]

申请自定义类型的连续空间,需要没申请一块空间,都需要调用构造函数进行申请,释放时,也需要没释放一次空间,都需要调用析构函数。👇
在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值