文编写参考狄泰软件学院唐佐林老师的视频课程,如有错误之处,欢迎指正。
一、c++中内存申请与c语言内存申请的异同
1、对于new关键字和malloc函数
new关键字的功能类似于c语言中的malloc,它们都是从堆空间中申请一段内存。下面几点是两者之间的异同点:
- new是c++中的关键字,而malloc是c库提供的函数,有些c编译器可能是没有这个库的,那么就会导致不能申请动态空间
- new是以具体类型为单位进行内存分配,而malloc是以字节为单位进行内存分配。
- new在申请单个类型变量时可以进行初始化,而malloc不可以,calloc函数虽然是将空间里的值初始化为0,但是并不是初始化为用户希望的值,所以还不是真正意义上的初始化。
- new能够触发构造函数的调用,malloc仅分配需要的内存空间。
在c++中在堆空间为对象申请空间时,是需要调用构造函数的,而这个必须通过new关键字来实现,因为采用malloc函数只是说从堆空间中申请一段内存,但是并不会调用构造函数,也就是说生成的对象是不合法的.
- 对象的创建只能使用用new,malloc函数不适合面向对象开发
2、对于delete关键字和free函数
- delete在所有c++编译器都被支持
- free在没有c库的时候不能够被调用,而某些开发系统中是没有c库的
- delete能够触发析构函数的调用,free仅仅归还之前分配的内存空间
- 对象的销毁只能够用delete,free不适合面向对象开发
- new是通过delete释放空间的,而malloc是以free来释放空间的。对此要特别注意的是:
(1)对单个类型变量的释放和对数组的释放在形式上是有区别的,对数组空间进行释放时一定要加上[]。
(2)用new就一定用delete,用malloc就用free,不能够混合使用,原因如下:
因为这样虽然可以通过编译,但是这是会带来问题的,假设用new为对象在对空间中申请了一段内存,那么此时就会出发构造函数的调用,从而完成对象的构造,当使用delete关键字来归还空间时,首先会调用析构函数,进行对象的销毁,然后再归还空间,但是当使用free函数来归还空间,这时是不会自动调用析构函数的,它完成的工作仅仅是归还堆空间,那么如果此时对象里面的成员变量也是从堆空间里面申请的,那么这时就会造成内存泄露。同样地,我们不能够用delete用mallocd申请的堆空间,有可能通过编译,但是同样的也会带来问题,有可能这个问题会暂时没出现,因为用malloc函数申请堆空间时并没有生成一个合法的对象,而用delete关键字就会调用析构函数,去调用一个不合法对象的析构函数是很可能会出现问题的。
二、例程理解
例程1:
#include<iostream>
using namespace std;
int main()
{
int* p1=new int(5);
char* p2=new char('a');
float* p4=new float(2.1f);
cout<<"*p1="<<*p1<<endl;
cout<<"*p2="<<*p2<<endl;
cout<<"*p4="<<*p4<<endl;
delete p1;
delete p2;
delete p4;
int* p3=new int[10];
for(int i=0;i<10;i++)
{
p3[i]=i+1;
cout<<"p3"<<"["<<i<<"]="<<p3[i]<<endl;
}
delete[] p3;
return 0;
}
例程2:
#include <iostream>
#include <string>
#include <cstdlib>//C标准通用实用库,此标头定义了几个通用功能,包括动态内存管理,随机数生成,与环境的通信,整数算术,搜索,排序和转换。
using namespace std;
class Test
{
int* mp;
public:
Test()
{
cout << "Test::Test()" << endl;
mp = new int(100);
cout << *mp << endl;
}
~Test()
{
delete mp;//归还内存空间
cout << "~Test::Test()" << endl;
}
};
int main()
{
Test* pn = new Test;//用c++的方式,申请空间的同时会调用构造函数,完成对象的构造
Test* pm = (Test*)malloc(sizeof(Test));//用c语言的方式,只负责申请空间,不负责对象的构造,因此生成的对象不合法
delete pn;//会先调用析构函数销毁对象,然后归还空间
free(pm);//只负责归还空间,而不负责销毁对象
return 0;
}
分析:此处只调用了一个构造函数和析构函数,因此证明了此文开头的一些结论,这里也可修改程序验证其余的结论,这里就不一一演示了。