前言:本篇主要解释了C/C++中动态申请/释放内存的方式,以及C++和C语言中中申请内存方式的相同/异点。
C语言的动态申请内存的方式:
1.malloc: 以int为例-->
int * arr = (int*)malloc(sizeof(int) * 10);
在C语言中我们知道使用malloc申请的内存是未初始化的,还需要我们手动来初始化:
int * arr = (int*)malloc(sizeof(int) * 10);
for (int i = 0; i < 10; i++)
{
*arr = i;
cout << *arr << " ";//打印测试
++arr;
}
2.calloc,以int为例子-->
int* newSpace = (int*)calloc(sizeof(int) * 10, 0);
很明显,calloc支持将申请后的内存初始化赋值
3.realloc,以int为例子-->
int* Space = (int*)malloc(sizeof(int) * 5);
int* newSpace = (int*)realloc(Space,sizeof(int)*10);
realloc可以扩容一块已经申请的内存,具体细节C语言相关帮助文档有详细说明:std::realloc - C++中文 - API参考文档 (apiref.com)
上述三种当时申请的内存在C语言中都是通过free释放的:
free(arr);
free(newSpace);
上述三个动态申请内存的函数在处理内置类型固然还可以,但是当涉及到自定义类型时,就显得有些乏力了,所以C++引入了新的内存申请方式-->new.delete
new:
先来看看new申请内置类型的内存,以int类型为例:
/*只申请内存,不初始化*/
int* Space1 = new int;
/*申请内存后并初始化值*/
int* Space2 = new int(1);
/*申请连续的空间*/
int* Space3 = new int[5];
/*申请连续的空间并赋值*/
int* Space4 = new int[5] {1,2,3,4,5};
delete,以上述为例,用来释放new出来的内存.
/*只申请内存,不初始化*/
int* Space1 = new int;
/*申请内存后并初始化值*/
int* Space2 = new int(1);
/*申请连续的空间*/
int* Space3 = new int[5];
/*申请连续的空间并赋值*/
int* Space4 = new int[5] {1,2,3,4,5};
delete Space1;
delete Space2;
delete Space3;
/*释放连续的内存要使用delete[]*/
delete[] Space4;
new和delete对于C++的自定义类型(类):
简单来说,在申请自定义类型的空间时,new会调用自定义类型的构造函数,delete会调用自定义类型的析构函数,这在c语言中的内存申请函数无法做到的。
示例:
class newTestClass
{
public:
newTestClass(int data = 0)
:_data(data)
{
/*测试打印看会出现什么现象?*/
cout << "调用newTestClass的构造函数" << endl;
}
~newTestClass()
{
_data = 0;
/*测试打印看会出现什么现象?*/
cout << "调用newTestClass的析构函数" << endl;
}
private:
int _data;
};
int main()
{
newTestClass* space = new newTestClass;
delete space;
return 0;
}
结果很显而易见-->
同样的,如果要申请连续的自定义类型的空间,使用new _type[],释放使用delete[] + _type
使用malloc/calloc/realloc均不会自动调用自定义类型的构造和析构函数!
class newTestClass
{
public:
newTestClass(int data = 0)
:_data(data)
{}
void* operator new(size_t size)
{
//
}
void operator delete(void* ptr)
{
//
}
~newTestClass()
{
_data = 0;
}
private:
int _data;
};
如果类中重载了new,那么当new这个类类型的对象时,会自定调用该类中重载的operator new来申请内存。
2.浅谈全局的operator new.operaotr delete:
copy了一份源码:
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);
}
void operator delete(void* pUserData)
{
_CrtMemBlockHeader* pHead;
RTCCALLBACK(_RTC_Free_hook, (pUserData, 0));
if (pUserData == NULL)
return;
_mlock(_HEAP_LOCK);
__TRY
pHead = pHdr(pUserData);
_ASSERTE(_BLOCK_TYPE_IS_VALID(pHead->nBlockUse));
_free_dbg(pUserData, pHead->nBlockUse);
__FINALLY
_munlock(_HEAP_LOCK);
__END_TRY_FINALLY
return;
}