C++中动态内存管理的方式与C语言有所不同,在c++中通过new和delete运算符进行动态内存管理,通过深入剖析new/new[]和delete/delete[]来对c++的内存管理有更深入的了解
C语言
堆上使用malloc/calloc/realloc/free进行动态内存管理, malloc/calloc/realloc用来在堆上开辟空间,free将申请的空间释放掉
面试题:malloc/calloc/realloc三者之间的区别?
答:1)void *malloc(size_t size);size表示要分配的字节数,其中要检测空间是否开辟成功,开辟失 败时返回0
2)作用:在内存中分配一个元素被初始化为0的数组。
原型:void *calloc(size_t num,size_t size);num表示元素的个数,size表示每个元素的大小
返回值:返回一个指向所分配空间的void指针。
3)作用:重新分配内存块
原型:void *realloc(void* memblock,size_t size);memblock指向原先分配的内存块,size表示新的内 存块的字节大小。
返回值:返回一个指向重新分配(可能移动了)的内存块的大小。
注意:堆上的内存需要用户自己来管理,动态malloc/calloc/realloc的空间,必须free掉,否则会造成内存泄漏
栈上开辟的内存由编译器自动维护,不需要用户显式释放
C++
下面看一个例子来显示new/new[]/delete/delete[]的使用:
void Test()
{
int* p1 = new int;
int* p2 = new int(3);
int* p3 = new int[3];
delete p1;
delete p2;
delete[] p3;
}
注意:new和delete,new[]和delete[]一定要匹配使用!
malloc/free和new/delete的区别和联系:
1)它们都是动态管理内存的入口
2)malloc/free是C/C++标准库的函数,new/delete是C++操作符
3)malloc/free只是动态分配内存空间/释放空间。而new/delete除了分配空间还会调用构造函数和析构函数进行初始化与清理(清理成员)
4)malloc/free需要手动计算类型大小且返回值会void*,new/delete 可自己计算类型的大小,返回对应类型的指针
深度剖析new/new[]/delete/delete[]
new:
delete:
new[]:
delete[]:
用malloc/free模拟实现new/delete/new[]/delete[]
class Test
{
public:
Test()
{
_t = 0;
cout << "Test()" << this << endl;
}
~Test()
{
cout << "`Test()" << this << endl;
}
private:
int _t;
};
//模拟实现new
void* New()
{
//先开辟空间
Test* pt = (Test*)malloc(sizeof(Test));
if (NULL == pt)
{
assert(false);
return NULL;
}
//在开辟的空间上执行构造函数
new(pt) Test;
return pt;
}
//模拟实现new[]
void* NewArray(size_t N)
{
//先开辟空间,多开辟4个字节的空间用来存放对象的个数N
int* p = (int*)malloc(sizeof(Test)*N + 4);
if (NULL == p)
{
assert(false);
return NULL;
}
*p = N;
//在开辟的空间上执行构造函数
Test* pt = (Test*)(p + 1);
for (size_t i = 0; i < N; ++i)
{
new(pt + i) Test;
}
return pt;
}
//模拟实现delete
void Delete(Test* p)
{
if (NULL == p)
return;
//先调用析构函数清理资源
p->~Test();
//再释放空间
free(p);
}
//模拟实现delete[]
void DeleteArray(Test* pt)
{
if (NULL == pt)
{
assert(false);
return;
}
//取出对象的个数,再调用析构函数清理资源
int *p = (int*)pt - 1;
int N = *p;
for (int i = N - 1; i >= 0; --i)
pt[i].~Test();
//释放空间
free(p);
}