CC++内存管理

CC++内存管理,第1张

1. C语言中的动态内存管理方式 1.1 malloc/calloc/realloc

在C语言中提供了三个方式来动态开辟空间,分别是malloc、calloc、realloc,

那他们三者有什么区别呢?


malloc:在堆上开辟空间,但对开辟的空间不进行初始化。

calloc:在堆上开辟空间,并对开辟的空间进行初始化,如果是int等类型则初始化为0,如果是指针类型则初始化为NULL。

realloc:对已开辟的空间进行扩充或者缩小,如果是进行扩充,已开辟空间的内容会被保存,如果是进行缩小,可能会丢失原空间的内容。

2. C++的动态内存管理方式

C语言内存管理方式在C++中可以继续使用,但有些地方就无能为力而且使用起来比较麻烦,因此C++又提出 了自己的内存管理方式:通过new和delete *** 作符进行动态内存管理。

2.1 new/delete *** 作内置类型

我们可以看到当未赋值的new一个空间时,不会对其初始化,而是赋了一个随机值。

注意:

当类型后面跟的()时,()里面是数字表示对开辟的空间进行初始化的值

当类型后面跟的是[]时,[]里面是数字表示开辟的空间个数

那我们既然开辟了空间,那就必然存在释放空间的说法,那在C语言中开辟的空间是如何释放的呢?

我们知道使用free()函数来对开辟的空间进行释放,那在C++中是使用什么来进行释放的呢?

我们可以发现是使用delete函数来进行释放。

注意当开辟一个数组时,我们需要使用delete[]来进行。

2.2 new/delete *** 作自定义类型

开始我们说到,C语言的内存管理方式在某些方面很麻烦,这里指的就是 *** 作自定义类型,为什么呢?

在类和对象中,我们学习到了构造函数和析构函数,C语言的内存管理方式(malloc、calloc)当为自定义类型开辟空间后,不会调用构造函数,为其释放空间时,不会调用析构函数,这样就会引起很多的麻烦,因此我们使用new和delete来解决这类问题。

3. operator new和operator delete函数 3.1 new和delete的底层原理

new和delete是用户进行动态内存申请和释放的 *** 作符,operator new 和operator delete是系统提供的全局函数,new在底层调用operator new全局函数来申请空间,delete在底层通过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
 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); /* 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通过调用operator new和operator delete来实现内存管理,而operator new和operator delete是malloc和free进行的封装。

因此new和delete的底层也是malloc和free。

4. new和delete的实现原理 4.1 内置类型的创建

如果是对于内置类型的创建或者销毁,malloc和free与new和delete基本一致,唯一不同的是当开辟空间失败,malloc会返回NULL,而new会抛异常。

4.2 自定义类型

1. new

调用operator new开辟空间

调用自定义类型中的构造函数

2. delete

调用自定义类型中的析构函数

调用operator delete释放空间

3. new type[N]

调用operator new[]开辟空间,实际是调用N次operator new来开辟空间

调用N次自定义类型的构造函数

4. delete[]

调用N次自定义类型的析构函数

调用operator delete[]释放空间,实际是调用operator delete来释放空间

5. 定位new表达式

定位new表达式是在已分配的原始内存空间中调用构造函数初始化一个对象。

使用场景: 定位new表达式在实际中一般是配合内存池使用。因为内存池分配出的内存没有初始化,所以如果是自定义类型的对象,需要使用new的定义表达式进行显示调构造函数进行初始化。

class Test
{
public:
 Test()
 : _data(0)
 {
 cout<<"Test():"<
6. malloc/free和new/delete的区别

相同点:

mallo/free和new/delete都是在堆上开辟空间,都需要手动释放空间。

不同点:

1. malloc和free是函数,new/delete是 *** 作符

2. malloc开辟的空间不会初始化,new开辟的空间会初始化

3. malloc开辟空间需要手动计算开辟空间的字节大小,new只需要跟上开辟的个数

4. malloc开辟的空间返回值是void*,需要强转类型,new不需要强转类型

5. malloc开辟空间失败会返回NULL,而new开辟失败则会抛异常

6. 开辟/释放空间后,malloc/free不会调用构造函数和析构函数,而new/delete会调用构造函数和析构函数。

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/langs/1324406.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-06-12
下一篇2022-06-12

发表评论

登录后才能评论

评论列表(0条)