1.堆内存

  堆(heap)是内存空间。堆是区别于栈区、全局数据区和代码区的另一个内存区域。堆允许程序在运行时(而不是在编译时),申请某个大小的内存空间。
  在通常情况,一旦定义了一个数组, 那么不管这个数组是局部的(在栈中分配)还是全局的(在全局数据区分配),它的大小在程序编译时即是已知的,因为必须用一个常数对数组的大小进行声明:
    int i=10;
    //….
    int a[i];  //error: 定义时不允许数组元素个数为变量
    int b[20]; //ok

  但是,在编写程序时不是总能知道数组应该定义成多大,如果定义数组元素多了就浪费内存了,更何况有时候根本不知道需要使用多少个数组元素。因此,需要在程序运行时从系 统中获取内存。
  程序在编译和连接时不予确定这种在运行中获取的内存空间,这种内存环境随着程序运行的进展而时大时小,这种内存就是堆内存,所以堆内存是动态的。堆内存也称动态内存

2.获得堆内存

  函数malloc()是C程序获得堆内存的一种方法,它在alloc.h头文件中声明。malloc()函数的原型为:
    void* malloc(size_t size);
    size_t即unsigned long。

  该函数从堆内存中“切下”一块size大小的内存,将指向该内存的地址返回。该内存中的内容是未知的。
  例如,下面的程序从堆中获取一个整数数组,赋值并打印:
    //**********************
    //**     func1.cpp    **
    //**********************

    #include <iostream.h>
    #include <alloc.h>

    void main()
    {
        int arraysize; //元素个数
       int *array;
       cout <<"please input a number of array:\n";
      cin >> arraysize;

       array = (int*)malloc(arraysize * sizeof(int));

      //堆内存分配

       for(int count = 0; count < arraysize; count++)
         array[count] = count * 2;

       for(int count = 0; count < arraysize; count++)
         cout << array[count] << " ";

       cout << endl;
    }


  运行结果为:
    C>func1
    please input a number Of array elements:
    10
    0  2  4  6  8  10  12  14  16  18

  程序编译和连接时,在栈中分配了arraysize整型变量和array整型指针变量空间。程序运行中,调用函数malloc(),并以键盘输入的整数值作为参数。malloc()函数在堆中寻找未被使用的内存,找够所需的字节数后返回该内存的起始地址。因为malloc()函数并不知道用这些内存干什么,所以它返回一个没有类型的指针。但对整数指针array来说,malloc()函数的返回值必须显式转换成整数类型指针才能被接受(ANSIC++标准)。
  一个拥有内存的指针完全可以被看作为一个数组,而且位于堆中的数组和位于栈中的数组结构是一样的。表达式“array[count] = count * 2;”正是这样应用的。
  上例中并没有保证一定可以从堆中获得所需内存。有时,系统能提供的堆空间不够分配,这时系统会返回一个空指针值NULL。这时所有对该指针的访问都是破坏性的,因此调用malloc()函数更完善的代码应该如下:
    if((array = (int *)malloc(arraysize * sizeof(int) == NULL)
    {
       cout << "can’t allocate more memory, terminate. \n";
       exit(1);
    }

3.释放堆内存

  我们把堆看作是可以按要求进行分配的资源或内存池。程序对内存的需求量随时会增大或缩小。程序在运行中可能经常会不再需要由malloc()函数分配的内存,而且程序还未运行结束,这时就需要把先前所占用的内存释放回堆以供程序的其它部分所用。
  函数free()返还由malloc()函数分配的堆内存,其函数原型为:
    void free(void*);
  free()参数是先前调用malloc()函数时返回的地址。把其它值传给free()很可能会造成灾难性的后果。
  例如,下面的程序完善程序mallocFunc.cpp:
    //***********************
    //**     func2.cpp    **
    //***********************

    #include <iostream.h>
    #include <alloc.h>

    void main()
    {
       int arraysize; //元素个数
       int *array;
       cout << "please input a number of array:\n";
      cin >> arraysize;

        if ((array=(int*)malloc(arraysize*sizeof(int))) == NULL)
      {

          cout<<"can’t allocate more memory,terminating.\n";
           return;

}

     for(int count=0; count<arraysize; count++)
       array[count]=count*2;

     for(int count=0; count<arraysize; count++)
       cout <<array[count] <<" ";

     cout <<endl;
     free(array); //释放堆内存
    }

  运行结果为:
    C>ch8_8
    please input a number Of array elements:
    10
    0  2  4  6  8  10  12  14  16  18

4.new与delete

  new和delete是C++专有的操作符,它们不用头文件声明。new类似于函数malloc(),分配堆内存,但比malloc()更简练。new的操作数为数据类型,它可以带初始化值表或单元个数。new返回一个具有操作数之数据类型的指针。返回delete类似于函数free(),释放堆内存。delete的操作数是new返回的指针,当返回的是new分配的数组时,应该带[]。
  例如,下面的程序是程序ch8_8.cpp的新版:
    //*********************
    //** ch8_9.cpp **
    //*********************

    #include <iostream.h>
    //#include <alloc.h> //无须头文件

    void main()
    {
     int arraysize; //元素个数
     int *array;
     cout <<"please input a number of array:\n";
      cin >>arraysize;

     if((array=new int[arraysize])==NULL){ //分配堆内存
      cout<<"can’t allocate more memory,terminating.\n";
      return ;
     }

     for(int count=0; count<arraysize; count++)
       array[count]=count*2;

     for(int count=0; count<arraysize; count++)
       cout <<array[count] <<" ";

     cout <<endl;
     delete[]array; //释放堆内存
    }

  运行结果为:
    C>ch8_9
    please input a number Of array elements:
    10
    0  2  4 6  8  10  12  14  16  18

  上例中可以看到,Hew的返回值无须显式转换类型, 直接赋给整数指针array;new的操作数是int[arraysize],它只要指明什么类型和要几个元素就可以了,它比函数malloc()更简洁。事实上,new和delete比函数malloc()和free()具有更丰富的功能。在第14章将进一步展开new和delete的讨论。


评论

该日志第一篇评论

发表评论

评论也有版权!