1. 程式人生 > >C++堆記憶體,棧記憶體,new,不new之間的關係梳理

C++堆記憶體,棧記憶體,new,不new之間的關係梳理

一、一個由C/C++編譯的程式佔用的記憶體分為以下幾個部分

1、棧區(stack)—由編譯器自動分配釋放 ,存放函式的引數值,區域性變數的值等。其操作方式類似於資料結構中的棧
2、堆區(heap)— 一般由程式設計師分配釋放,若程式設計師不釋放,程式結束時可能由OS回收。注意它與資料結構中的堆是兩回事,分配方式倒是類似於連結串列
3、全域性區(靜態區)(static)—,全域性變數和靜態變數的儲存是放在一塊的,初始化的全域性變數和靜態變數在一塊區域,未初始化的全域性變數和未初始化的靜態變數在相鄰的另一塊區域。-程式結束後有系統釋放
4、文字常量區—常量字串就是放在這裡的。 程式結束後由系統釋放
5、程式程式碼區—存放函式體的二進位制程式碼。

//main.cpp
inta = 0; //全域性初始化區
char*p1; //全域性未初始化區
main()
{
    int b; //棧 
    char s[] = "abc"; //棧 
    char *p2; //棧  
    char *p3 = "123456"; //123456\0在常量區,p3在棧上。  
    static int c =0//全域性(靜態)初始化區 
    p1 = (char *)malloc(10);  
    p2 = (char*)malloc(20);*   //分配得來的10和20位元組的區域就在堆區, 但是注意p1、p2本身是在棧中的 
    strcpy
(p1,"123456"); //123456\0放在常量區,編譯器可能會將它與p3所指向的"123456"優化成一個地方。 }

二、new建立類物件與不new區別
下面是自己總結的一些關於new建立類物件特點:

1.new建立類物件需要指標接收,一處初始化,多處使用
2.new建立類物件使用完需delete銷燬
3.new建立物件直接使用堆空間,而區域性不用new定義類物件則使用棧空間
4.new物件指標用途廣泛,比如作為函式返回值、函式引數等
5.頻繁呼叫場合並不適合new,就像new申請和釋放記憶體一樣

char* GetString(void) {
 char
p[] = "hello world"; return p; //此處編譯器會提出warning } char* GetString(void) { char* p = "hello world"; return p; }

第一種p是在棧上分配記憶體,函式結束後將會自動釋放,p指向的記憶體區域內容不是”hello world”,而是未知的內容。
第二種是返回靜態儲存的記憶體,這裡的”hello world”是常量字串,位於靜態儲存區,它在程式生命期內恆定不變。無論什麼時候呼叫GetString,均返回一個“只讀”的記憶體塊。

三、delete用法
  1. 刪除單變數地址空間

  int *a = new int;
  delete a;   //釋放單個int的空間

  2. 刪除陣列空間

  int *a = new int[5];
  delete []a;    //釋放int陣列空間
  3.關於Vector中存放指標的問題,在進行清空的時候比較安全的一種做法是:
    std::vector<ClassName *> ClassNameVec;
    ...push_back(new ClassName());
    std::vector<ClassName *>::iterator ClassNameIt = ClassNameVec.begin();
    for(;ClassNameIt != ClassNameVec.end();++ClassNameIt)
    {    
        if(*ClassNameIt != NULL)
        {
          delete *ClassNameIt;
          *ClassNameIt = NULL;
        }  
    }
    ClassNameVec.clear();