C++動態內存分配(堆)

1.堆內存分配 :

C/C++定義了4個內存區間:
    代碼區,全局變量與靜態變量區,局部變量區即棧區,動態存儲區,即堆(heap)區或自由存儲區(free store)。
堆的概念:
通常定義變量(或對象),編譯器在編譯時都可以根據該變量(或對象)的類型知道所需內存空間的大小,從而系統在適當的時候爲他們分配確定的存儲空間。這種內存分配稱爲靜態存儲分配;
    有些操作對象只在程序運行時才能確定,這樣編譯時就無法爲他們預定存儲空間,只能在程序運行時,系統根據運行時的要求進行內存分配,這種方法稱爲動態存儲分配。所有動態存儲分配都在堆區中進行。
當程序運行到需要一個動態分配的變量或對象時,必須向系統申請取得堆中的一塊所需大小的存貯空間,用於存貯該變量或對象。當不再使用該變量或對象時,也就是它的生命結束時,要顯式釋放它所佔用的存貯空間,這樣系統就能對該堆空間進行再次分配,做到重複使用有限的資源。
2.堆內存的分配與釋放
堆空間申請、釋放的方法:
在C++中,申請和釋放堆中分配的存貯空間,分別使用new和delete的兩個運算符來完成:  

指針變量名=new 類型名(初始化式);
         delete 指針名;
例如:1、 int *pi=new int(0);
      它與下列代碼序列大體等價:
      2、int ival=0, *pi=&ival;
區別:pi所指向的變量是由庫操作符new()分配的,位於程序的堆區中,並且該對象未命名。  
堆空間申請、釋放說明:
⑴.new運算符返回的是一個指向所分配類型變量(對象)的指針。對所創建的變量或對象,都是通過該指針來間接操作的,而且動態創建的對象本身沒有名字。
⑵.一般定義變量和對象時要用標識符命名,稱命名對象,而動態的稱無名對象(請注意與棧區中的臨時對象的區別,兩者完全不同:生命期不同,操作方法不同,臨時變量對程序員是透明的)。
⑶.堆區是不會在分配時做自動初始化的(包括清零),所以必須用初始化式(initializer)來顯式初始化。new表達式的操作序列如下:從堆區分配對象,然後用括號中的值初始化該對象。
3.堆空間申請、釋放演示:
⑴.用初始化式(initializer)來顯式初始化
int *pi=new int(0);
⑵.當pi生命週期結束時,必須釋放pi所指向的目標:
         delete pi;
注意這時釋放了pi所指的目標的內存空間,也就是撤銷了該目標,稱動態內存釋放(dynamic memory deallocation),但指針pi本身並沒有撤銷,它自己仍然存在,該指針所佔內存空間並未釋放。

 
4. 在堆中建立動態一維數組
①申請數組空間:
指針變量名=new 類型名[下標表達式];(可以看做是申請一連串的內存空間而不將其具象化爲數組)
注意:“下標表達式”不是常量表達式,即它的值不必在編譯時確定,可以在運行時確定。
②釋放數組空間:
delete [ ]指向該數組的指針變量名;
注意:方括號非常重要的,如果delete語句中少了方括號,因編譯器認爲該指針是指向數組第一個元素的,會產生回收不徹底的問題(只回收了第一個元素所佔空間),加了方括號後就轉化爲指向數組的指針,回收整個數組。delete [ ]的方括號中不需要填數組元素數,系統自知。即使寫了,編譯器也忽略。
#include <iostream.h>
#include <string.h>
void main(){
     int n;
     char *pc;
     cout<<"請輸入動態數組的元素個數"<<endl;
     cin>>n; //n在運行時確定,可輸入17
     pc=new char[n]; //申請17個字符(可裝8個漢字和一個結束符)的內存空間
     strcpy(pc,“堆內存的動態分配”);//
     cout<<pc<<endl;
     delete []pc;//釋放pc所指向的n個字符的內存空間
     return ; }
5. 動態一維數組的說明
①一定注意:delete []pc是將n個字符的空間釋放,而用delete pc則只釋放了一個字符的空間;
② 如果有一個char *pc1,令pc1=p,同樣可用delete [] pc1來釋放該空間。儘管C++不對數組作邊界檢查,但在堆空間分配時,對數組分配空間大小是紀錄在案的。
③ 沒有初始化式(initializer),不可對數組初始化。


6關於多維數組
b3=new int [1] [20] [30];
b2=new int [30] [20];
刪除這兩個動態數組可用下式:
delete [] b3;  //刪除(釋放)三維數組;
delete [] b2;  //刪除(釋放)二維數組

7 堆對象與構造函數
 通過new建立的對象要調用構造函數,通過deletee刪除對象也要調用析構函數。
CGoods *pc;
pc=new CGoods;  //分配堆空間,並構造一個無名
                               //的CGoods對象;
…….
delete pc;  //先析構,然後將內存空間返回給堆;

一定注意:由堆區創建對象數組,只能調用缺省的構造函數,不能調用其他任何構造函數。如果沒有缺省的構造函數,則不能創建對象數組。

例子:
class CGoods{
           char Name[21];
           int  Amount;
           float Price;
           float Total value;
public:
  CGoods(){}; //缺省構造函數。因已有其他構造函數,系統不會再自動生成缺省構造,必須顯式說明。
  CGoods(char* name,int amount ,float price){
            strcpy(Name,name);
            Amount=amount;
            Price=price;
            Total_value=price*amount;  }
            ……
};//類聲明結束
//下面注意如何使用:
void main(){
  int n;
  CGoods *pc,*pc1,*pc2;
  pc=new CGoods(“夏利2000”,10,118000);
  //調用三參數構造函數
  pc1=new CGoods();  //調用缺省構造函數
  cout<<’輸入商品類數組元素數’<<endl;< div="" style="word-wrap: break-word;">
  cin>>n;
  pc2=new CGoods[n];
 //動態建立數組,不能初始化,調用n次缺省構造函數
  ……
  delete pc;
  delete pc1;
  delete []pc2;  }


本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/yanjiaye520/archive/2010/12/01/6048346.aspx

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