#include <iostream>
#include<stdio.h>
#include <new>//需要添加该头文件
using namespace std;
cons t int ARRLEN = 100;
int static_buf[ARRLEN];//静态区
const int N = 5;
int main()
{
int *p1,*p2;
cout<<"static_buf address:"<<static_buf<<endl;
for(int j = 0; j < 3; j++)
{
cout<<"\n\n\n";
p1 = new int[N];
p2 = new (static_buf)int[N];//指定区域分配内存
for(int i = 0; i < N; i++)
{
p1[i] = p2[i] = i;
cout<<"p1-->"<<&p1[i]<<" value:"<<p1[i]<<" ";
cout<<"p2-->"<<&p2[i]<<" value:"<<p2[i]<<endl;//打印出每个元素的地址和值
}
}
return 0;
}
运行结果为:
可见,经过三次循环后p2指向的数组的地址并没有改变,而且该地址就是在静态存储器中分配的static_buf的地址。这说明我们可以通过new的这种语法对已经存在的内存区域上构造数据。而且我们可以发现new不仅仅可以在堆中分配内存,而且可以使用静态存储区中的内存。但是这样p1指向的内存会产生泄露,所以修改代码:
#include <iostream>
#include<stdio.h>
#include <new>//需要添加该头文件
using namespace std;
const int ARRLEN = 100;
int static_buf[ARRLEN];//静态区
const int N = 5;
int main()
{
int *p1,*p2;
cout<<" static_buf address:"<<static_buf<<endl;
for(int j = 0; j < 3; j++)
{
cout<<"\n\n\n";
p1 = new int[N];
p2 = new (static_buf)int[N];//指定区域分配内存
for(int i = 0; i < N; i++)
{
p1[i] = p2[i] = i;
cout<<" p1-->"<<&p1[i]<<" value:"<<p1[i]<<" ";
cout<<" p2-->"<<&p2[i]<<" value:"<<p2[i]<<endl;//打印出每个元素的地址和值
}
delete []p1;
}
return 0;
}
运行结果为:
可见,现在每次delete掉p1,再次new后,数组的内存地址是一样的。
所以我们应该可以根据这个区别来判断是否发生了内存泄露。如果程序请求分配一块堆内存,应该是根据堆的内存指针来决定所分配内存的地址的,如果这块内存已经delete掉了,那么第二次分配的内存地址应该和第一次的地址一样(假设中间没有任何内存操作,不考虑其他程序干扰)。
总结一下:
1.p1存在栈中,存储的地址指向堆。
p1需要手动释放。
p2存在栈中,存储的地址指向静态区。
p2自动释放。避免了内存泄露,牺牲了内存访问的独立性(第二次new的时候,第一次new产生的数据的没了)。
2.由于p2的这种特性,所以本例中的static_buf一般在工程应用中作为一个缓冲区。