从c++这门语言的角度来说,当你使用new关键字分配内存时,是在堆区开辟一段内存,这块内存是交给程序员自行管理的,如果不delete是会造成这段内存永远占据你电脑的内存不被释放。
从代码规范的角度来说,new和delete应该成对出现。
但实际上,对于现代的编译器和操作系统它是会在程序结束时自动释放未释放的内存。
换言之,即使程序员自己不delete,编译器会帮你释放。
以下是两组实验,证明上述内容
实验一:
1、先调用程序new一个内存空间,然后记下它的地址;
代码如下:
#include<iostream>
using namespace std;
int main()
{
cout<<new int();
}
结果:
2、再调用一个程序访问该内存,如果可以访问,则说明上一个程序new的内存并没释放,否则,则说明释放掉了。
#include<iostream>
using namespace std;
int main()
{
cout<<*(int*)0x861540<<endl;
}
结果如下:
发现这块内存已经无法访问,说明之前已经释放掉了;
这一个实验可能有人觉得说明不够充分,故有如下第二个实验
实验二:
1、先调用程序new若干内存,得到一组指针,将这些指针存入文件中;
代码如下:
#include<iostream>
#include<fstream>
using namespace std;
#define N 9000
int main()
{
ofstream ofs;
ofs.open("text.txt");
if(!ofs.is_open()) cout<<"error"<<endl;
for(int i=0;i<N;i++)
{
int* tmp=new int;
ofs.write((const char*)&tmp,sizeof(int*));
}
}
结果如下:(使用二进制存入,会出现乱码);
2、再调用另一个程序new若干个内存空间,将新生成的地址和文件里的地址进行比较,判断是否存在相同的地址
代码如下:
#include<iostream>
#include<fstream>
using namespace std;
#define N 9000
int main()
{
ifstream ofs;
ofs.open("text.txt",ios::out|ios::binary);
if(!ofs.is_open()) cout<<"error"<<endl;
int* a[N];
for(int i=0;i<N;i++)//将文件内容读入指针数组
{
ofs.read((char*)&a[i],sizeof(int*));
}
int cnt=0;
for(int i=0;i<N;i++)
{
int* p=new int(1);//new新的地址
for(int j=0;j<N;j++)
{
if(p==a[j])//如果新new的地址与之前new的地址(文件中的)相同,说明之前的内存已经被释放了
{
cout<<"经过了"<<i<<"次生成,找到了重复的生成的指针"<<p<<endl;
cnt++;
}
}
}
cout<<"找到了"<<cnt<<"个之前new过的内存空间"<<endl;
}
结果如下:
结果发现存在许多的新new的内存和之前new的内存相同,说明程序结束后会自动释放未释放的内存空间。
总结:以规范的角度来说,new和delete确实应该成对存在。但是实际上如果不手动释放并不会造成内存泄漏。