new限定区域分配内存

#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;//打印出每个元素的地址和值
        }
    }
    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;//为避免内存泄露,释放掉p1指向的内存
    }
    return 0;
}


运行结果如图:

可见,现在每次delete掉p1,再次new后,数组的内存地址是一样的。

所以我们应该可以根据这个区别来判断是否发生了内存泄露。如果程序请求分配一块堆内存,应该是根据堆的内存指针来决定所分配内存的地址的,如果这块内存已经delete掉了,那么第二次分配的内存地址应该和第一次的地址一样(假设中间没有任何内存操作,不考虑其他程序干扰)。

 

总结一下:

1.p1存在栈中,存储的地址指向堆。

p1需要手动释放。

 

p2存在栈中,存储的地址指向静态区。

p2自动释放。避免了内存泄露,牺牲了内存访问的独立性(第二次new的时候,第一次new产生的数据的没了)。

 

2.由于p2的这种特性,所以本例中的static_buf一般在工程应用中作为一个缓冲区。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章