
在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会调用构造函数和析构函数。
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)