在讨论c++内存管理之前,先来回忆一下c中的动态内存管理方式
1. c中动态内存管理方式
--堆上
c语言中使用malloc/calloc/realloc/free进行动态内存管理
malloc/calloc/realloc来在堆上开辟空间,free将申请的空间释放掉
·堆上的内存需要用户自己来管理,开辟的空间最后必须free掉,否则会造成内存泄漏。
--栈上
使用_alloca在栈上动态开辟内存,栈上开辟的内存由编译器自动维护,不需要用户显示释放。
--常见的内存泄漏
void memory()
{
//内存申请之后忘记了释放
int *pstr = (int *)malloc(10 * sizeof(int));
assert(pstr);
//程序逻辑不清,以为释放,实际内存泄漏
int *pstr1 = (int *)malloc(10 * sizeof(int));
int *pstr2 = (int *)malloc(10 * sizeof(int));
pstr1 = pstr2;
free(pstr1);
free(pstr2);//成为了野指针
//破坏了堆
char *pstr3 = (char *)malloc(5);//在堆上开辟了空间
strcpy(pstr3, "hahha");
free(pstr3);
//释放的地址和申请的地址不同
int *pstr4 = (int*)malloc(10 * sizeof(int));
assert(pstr4);
pstr4[0] = 0;
pstr4++;//指针自加,改变了开始的地址
free(pstr4);
}
2. c++内存管理方式
(1)c语言的内存管理方式在c++中同样适用,同时又提出了自己的内存管理方式。
通过new和delete运算符进行动态内存管理
--void test()
{
int *p = new int;//动态分配4个字节的空间
int *p1 = new int(3);//动态分配4个字节的空间并初始化为3
int *p2= new int[3];//动态分配三个int大小的空间
delete p;
delete p1;
delete[] p2;
}
·注意new和delete,new[]和delete[]一定要匹配使用,不然会造成内存泄漏
(2)new和delete 与malloc和free之间的联系与区别
·malloc和free是标准库函数,new和delete是操作符
·malloc和free只是分配空间,释放空间。但是new和delete 不仅分配空间,还会调用构造函数和析构函数,并且进行初始化,最后还要清理成员
·malloc和free需要手动计算类型大小并且返回值为void*,new和delete可自己计算类型的大小,返回对应类型的指针
3.深度剖析new ,delete,以及new[],delete[]
·delete的使用过程
·new[]的使用过程
·delete[]的使用过程
4.new操作符/操作符 new/定位new表达式
--new操作符
new和delete操作符是c++用来动态申请内存的关键字
--操作符new
操作符new/delete是一个函数
格式:operator new、operator delete
void *operator new(size_t size)//本质为malloc(size_t size)
-- operator new / operator delete/ operator new[]/ operator delete[]
·以上的函数和malloc,free的用法一样
·只负责分配释放空间,不会调用对象构造函数和析构函数
·所以,operator new 和delete只是malloc和free的一层封装。
--定位new的表达式
·定位new表达式是在已分配的原始内存空间中调用构造函数初始化一个对象
new (pstr)int;
new(pstr)int(10);
new(指针)类型(初始化列表)
·用free模拟实现delete[]
//模拟实现delete[]
void deletearray(student *ps)
{
if (NULL == ps)
{
return;
}
int *str = (int*)ps - 1;//再起始位置处向后偏移
int count = *str;//计算需要调用的次数
for (int i = count - 1; i >= 0; i--)
{
ps[i].~student();//调用析构函数,进行成员的清理,
}
free(ps);//释放空间
}