程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> 走進C++程序世界-----指針(動態申請空間和釋放空間)

走進C++程序世界-----指針(動態申請空間和釋放空間)

編輯:C++入門知識

使用關鍵字NEW分配內存     在講解分配內存之前,首先來理解下內存區劃分、內存分配、常量存儲區、堆、棧、自由存儲區、全局區這些也是初學者容易混淆的地方。我的博客中有一篇文章描述C語言中代碼分配情況,點擊鏈接      下面部分是轉載於:http://blog.sina.com.cn/s/blog_7edcf63b0100yhk9.html       一. 在c中分為這幾個存儲區 1.棧 ——由編譯器自動分配釋放 2.堆 ——一般由程序員分配釋放,若程序員不釋放,程序結束時可能由OS回收 3.全局區(靜態區)——全局變量和靜態變量的存儲是放在一塊的,初始化的全局變量和靜態變量在一塊區域,未初始化的全局變量和未初始化的靜態變量在相鄰的另一塊區域(C++中已經不再這樣劃分)。- 程序結束釋放 4.另外還有一個專門放常量的地方。- 程序結束釋放                                                                                                                                                在   (a)函數體中定義的變量通常是在棧上,   (b)用malloc, calloc, realloc等分配內存的函數分配得到的就是在堆上。   (c)在所有函數體外定義的是全局量,   (d)加了static修飾符後不管在哪裡都存放在全局區(靜態區),   (e)在所有函數體外定義的static變量表示在該文件中有效,不能extern到別的文件用,   (f)在函數體內定義的static表示只在該函數體內有效。   (7)另外,函數中的"adgfdf"這樣的字符串存放在常量區。   [cpp]  int a = 0; //全局初始化區    char *p1; //全局未初始化區    void main()   {        int b; //棧        char s[] = "abc"; //棧        char *p2; //棧        char *p3 = "123456"; //123456{post.content}在常量區,p3在棧上        static int c = 0; //全局(靜態)初始化區        p1 = (char *)malloc(10); //分配得來得10字節的區域在堆區        p2 = (char *)malloc(20); //分配得來得20字節的區域在堆區        strcpy(p1, "123456");        //123456{post.content}放在常量區,編譯器可能會將它與p3所指向的"123456"優化成一塊    }     二.在C++中,內存分成5個區,他們分別是堆、棧、自由存儲區、全局/靜態存儲區和常量存儲區 1.棧,就是那些由編譯器在需要的時候分配,在不需要的時候自動清楚的變量的存儲區。裡面的變量通常是局部變量、函數參數等。 2.堆,就是那些由new分配的內存塊,他們的釋放編譯器不去管,由我們的應用程序去控制,一般一個new就要對應一個delete。如果程序員沒有釋放掉,那麼在程序結束後,操作系統會自動回收。 3.自由存儲區,就是那些由malloc等分配的內存塊,他和堆是十分相似的,不過它是用free來結束自己的生命的。 4.全局/靜態存儲區,全局變量和靜態變量被分配到同一塊內存中,在以前的C語言中,全局變量又分為初始化的和未初始化的,在C++裡面沒有這個區分了,他們共同占用同一塊內存區。 5.常量存儲區,這是一塊比較特殊的存儲區,他們裡面存放的是常量,不允許修改(當然,你要通過非正當手段也可以修改) 明確區分堆與棧:     在bbs上,堆與棧的區分問題,似乎是一個永恆的話題,由此可見,初學者對此往往是混淆不清的,所以我決定拿他第一個開刀。     首先,我們舉一個例子: [cpp]   1 void f()   2 {    3      int* p=new int[5];   4  }     這條短短的一句話就包含了堆與棧,看到new,我們首先就應該想到,我們分配了一塊堆內存,那麼指針p呢?他分配的是一塊棧內存,所以這句話的意思就是:在棧內存中存放了一個指向一塊堆內存的指針p。在程序會先確定在堆中分配內存的大小,然後調用operator new分配內存,然後返回這塊內存的首地址,放入棧中,他在VC6下的匯編代碼如下:     00401028    push         14h     0040102A    call            operator new (00401060)     0040102F    add           esp,4     00401032    mov          dword ptr [ebp-8],eax     00401035    mov          eax,dword ptr [ebp-8]     00401038    mov          dword ptr [ebp-4],eax     這裡,我們為了簡單並沒有釋放內存,那麼該怎麼去釋放呢?是delete p麼?澳,錯了,應該是delete []p,這是為了告訴編譯器:我刪除的是一個數組,VC6就會根據相應的Cookie信息去進行釋放內存的工作。     好了,我們回到我們的主題:堆和棧究竟有什麼區別?     主要的區別由以下幾點:     1、管理方式不同;     2、空間大小不同;     3、能否產生碎片不同;     4、生長方向不同;     5、分配方式不同;     6、分配效率不同;     以下是摘與另外一篇博客C++中new和malloc的區別 . 一:new delete 是運算符,malloc,free是函數   malloc與free是C++/C語言的標准庫函數,new/delete是C++的運算符。它們都可用於申請動態內存和釋放內存。   對於非內部數據類型的對象而言,光用maloc/free無法滿足動態對象的要求。對象在創建的同時要自動執行構造函數,對象在消亡之前要自動執行析構函數。由於malloc/free是庫函數而不是運算符,不在編譯器控制權限之內,不能夠把執行構造函數和析構函數的任務強加於malloc/free。   因此C++語言需要一個能完成動態內存分配和初始化工作的運算符new,以及一個能完成清理與釋放內存工作的運算符delete。注意new/delete不是庫函數。   我們先看一看malloc/free和new/delete如何實現對象的動態內存管理,見示例。   [cpp]   class Obj      {      public :      Obj(void){ cout << “Initialization” << endl; }      ~Obj(void){ cout << “Destroy” << endl; }      void      Initialize(void){ cout << “Initialization” << endl; }      void      Destroy(void){ cout << “Destroy” << endl; }      };         void UseMallocFree(void)      {      Obj    *a = (obj *)malloc(sizeof(obj));     // 申請動態內存      a->Initialize();                          // 初始化      //…      a->Destroy();     // 清除工作      free(a);          // 釋放內存      }         void UseNewDelete(void)      {      Obj    *a = new Obj;    // 申請動態內存並且初始化      //…      delete a;             // 清除並且釋放內存      }     示例用malloc/free和new/delete如何實現對象的動態內存管理   類Obj的函數Initialize模擬了構造函數的功能,函數Destroy模擬了析構函數的功能。函數UseMallocFree中,由於malloc/free不能執行構造函數與析構函數,必須調用成員函數Initialize和Destroy來完成初始化與清除工作。函數UseNewDelete則簡單得多。   所以我們不要企圖用malloc/free來完成動態對象的內存管理,應該用new/delete。由於內部數據類型的“對象”沒有構造與析構的過程,對它們而言malloc/free和new/delete是等價的。   既然new/delete的功能完全覆蓋了malloc/free,為什麼C++不把malloc/free淘汰出局呢?這是因為C++程序經常要調用C函數,而C程序只能用malloc/free管理動態內存。   如果用free釋放“new創建的動態對象”,那麼該對象因無法執行析構函數而可能導致程序出錯。如果用delete釋放“malloc申請的動態內存”,理論上講程序不會出錯,但是該程序的可讀性很差。所以new/delete必須配對使用,malloc/free也一樣。   二:new delete在實現上其實調用了malloc,free函數。   三:new operator除了分配內存,還要調用構造函數。   malloc函數只是負責分配內存。     ×××××××××××××××××××××××××××××××××××以上是轉載部分××××××××××××××××××××××××××   [cpp]  #include <iostream>   /*C++ 內存分配、使用和刪除指針*/      using namespace std;      int main()   {          int localVariable = 5;       int *pLocal = &localVariable;       /*申請空間*/       int *pHeap = new int;          *pHeap = 7;          cout << "localVariable:" << localVariable << endl;       cout << "*pLocal:" << *pLocal << endl;       cout << "*pHeap:" << *pHeap << endl;       /*釋放空間*/       delete pHeap;          pHeap = new int;          *pHeap = 9;       cout << "pHeap: " << *pHeap << endl;       delete pHeap;          return 0;   }     輸出 [cpp]  localVariable:5   *pLocal:5   *pHeap:7   pHeap: 9   程序中每個new 都應該有對應delete ,否則會造成內存洩露。 [cpp]  //using new and delete   #include <iostream>      using namespace std;      class Simplecat{       public:           Simplecat();           ~Simplecat();       private:           int itsAge;   };      Simplecat::Simplecat()   {       cout << "Constructor called ******" << endl;       itsAge = 1;   }      Simplecat::~Simplecat()   {       cout << "Destructor called." << endl;   }      int main()   {       cout << "Simplecat Frisky******start *****"<< endl;       Simplecat Frisky;       cout << "Simplecat Frisky******end******"<< endl;              cout <<"new  Simplecat*******start******"<< endl;       Simplecat *ptags = new Simplecat;       delete ptags;       cout << "new Simplecat******end******"<<endl;          return 0;   }     [cpp]  Simplecat Frisky******start *****   Constructor called ******   Simplecat Frisky******end******   new  Simplecat*******start******   Constructor called ******   Destructor called.   new Simplecat******end******   Destructor called.       [cpp]    

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved