文章目录
一、回顾C中动态分配内存和回收的方式
C中动态分配内存的方式
1.malloc
2. calloc
3. realloc
回收方式
free
代码如下:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int *p1=(int *)malloc(sizeof(int));
printf("%d\n",*p1);//没有初始化
int *p2=(int *)calloc(1,sizeof (int));
printf("%d\n",*p2);//有初始化
int *p3=(int *)realloc(p2,sizeof(int)*10);
printf("%d\n",*p3);//有初始化
free(p1);
//free(p2);
//同一块堆区空间被多次释放会造成doublefree的现象,程序就会异常中止。
free(p3);
return 0;
}
结果展示:
总结:
- malloc在堆上开辟空间并没有进行初始化。
- calloc在堆上开辟空间是有初始化。
- relloc在堆上开辟空间都是有初始化。
- 同一块堆区空间被多次释放会造成double free的现象,程序就会异常中止。
二、C++中动态分配内存和回收的方式
C++提供了新的关键字new
来动态分配空间。
同时为了回收空间,又提供关键字delete
来释放空间。
在C++中支持malloc/free
,但是我们一般都使用 new/delete
2.1 分配
2.1.1 单个空间的分配
格式: 数据类型 *指针名 = new 数据类型;
如: int *p = new int;
在堆区分配 1 个 int 大小的空间。
2.1.2连续空间的分配
格式: 数据类型 *指针名 = new 数据类型[个数];
如: int *p = new int[5];
在堆区分配 5 个 int 大小的空间,连续的。
2.2 回收
2.2.1 单个空间的回收
delete 指针名;
2.2.2 连续的空间的回收
delete []指针名;
[]
里面不用写长度,但是[]
必须写,表示释放指针指向的连续空间。
2.3 举例说明
2.3.1 单个空间的举例
代码如下:
#include <iostream>
using namespace std;
int main()
{
int *pa=new int;
*pa=100;
cout << *pa << endl;
不初始化
int *pb=new int;
cout << *pb << endl;
//用0初始化
int *pc = new int();
cout<< *pc <<endl;
delete pc;
int *pd=new int(521);
cout << *pd << endl;
delete pa;
delete pb;
delete pc;
delete pd;
return 0;
}
结果展示:
总结:
new
分配的空间如果没有初始化,是随机值。- 当在类型后加上
()
时,new
分配的空间如果没有初始化,会自动用 0 进行初始化。 - 我们使用
new
时,一般都是直接初始化的操作,可以使用括号的方式直接初始化,new
后面的内置类型后加个括号表示编译器在括号取值初始化内置类型所开辟的内存中的值。 delete pa;
使用delete释放已经开辟的空间。
2.3.2 连续空间的举例
代码如下:
#include <iostream>
using namespace std;
int main()
{
int *pa=new int[10];
int i=0;
for(i=0;i<10;i++)
{
cout << pa[i] << ",";
}
cout << endl;
cout << "-----------------------------" << endl;
for(i=0;i<10;i++)
{
*(pa+i)=i;
}
for(i=0;i<10;i++)
{
cout << pa[i] << ",";
}
cout << endl;
cout << "-----------------------------" << endl;
int *pb=new int[10]{1,2,3};
for(i=0;i<10;i++)
{
cout << pb[i] << ",";
}
delete []pa;
delete []pb;
return 0;
}
结果展示:
总结:
int *pa=new int[10];
此种连续开辟空间,是没有初始化的。内存中的值有很多是随机值的。- 可以采用循环,或者采用
int *pb=new int[10]{1,2,3};
这种方式进行初始化。这是C++11的新语法。 - 如果是连续空间的开辟,一定要要使用
delete[]
的方式来释放。
三、自定义类类型中的new/delete
针对于内置类型而言,new
大体相当malloc
,delete
大体相当于free
但是如果自定义类类型
new
代表两种含义:开辟空间,调用类中的构造函数进行初始化。
delete
也代表两含义:即调用类中的析构函数,然后再释放空间。
关于构造与析构在之后的文章会详细讲解,感兴趣可以关注一下!
代码如下:
#include <iostream>
using namespace std;
struct Stu
{
Stu()
{
cout << "Stu的构造" << endl;
}
~Stu()
{
cout << "Stu的析构" << endl;
}
};
int main()
{
Stu *pstu=new Stu;
delete pstu;
return 0;
}
结果展示:
四、new与delete的底层
首先调用new
在底层调用的还是malloc分配的空间
malloc申请空间失败返回NULL;
new申请空间失败抛出一个异常;
五、C++中new与malloc之间的联系与区别
5.1 new与malloc之间的联系
new
的底层就是用malloc
实现的。
5.2 new与malloc之间的区别
- malloc如果申请空间失败返回
NULL
,new如果申请空间失败抛出异常bad_alloc();
- new就是按类型开辟空间的,而malloc是按字节为单位开辟空间的。
- new/delete 是C++的关键字,malloc/free是库函数。
- new可以在分配空间的同时进行初始化,malloc不可以。
- 当new分配的空间以
int *pc = new int();
,这种形式的时候,如果没有初始化,将用0进行初始化。如果是以int *pc = new int
形式出现的,则将是随机值。
malloc分配的空间如果没有初始化,是随机值,需要手动调用memset或者bzero函数来清空。 - new会根据类型自动计算分配空间的大小,malloc需要手动sizeof计算,传参。
- new是要什么类型,就返回什么类型的指针,malloc返回void *,需要进行强转。
对自定义类型来讲:
new 不仅开辟空间,还会调用自定类中的构造函数,malloc不会。
delete 不仅释放空间,还会在释放空间前先调用类中析构函数,free不会。