天天看點

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

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

1、棧區(stack)—由編譯器自動配置設定釋放 ,存放函數的參數值,局部變量的值等。其操作方式類似于資料結構中的棧

2、堆區(heap)— 一般由程式員配置設定釋放,若程式員不釋放,程式結束時可能由OS回收。注意它與資料結構中的堆是兩回事,配置設定方式倒是類似于連結清單

3、全局區(靜态區)(static)—,全局變量和靜态變量的存儲是放在一塊的,初始化的全局變量和靜态變量在一塊區域,未初始化的全局變量和未初始化的靜态變量在相鄰的另一塊區域。-程式結束後有系統釋放

4、文字常量區—常量字元串就是放在這裡的。 程式結束後由系統釋放

5、程式代碼區—存放函數體的二進制代碼。

//main.cpp
inta = ; //全局初始化區
char*p1; //全局未初始化區
main()
{
    int b; //棧 
    char s[] = "abc"; //棧 
    char *p2; //棧  
    char *p3 = "123456"; //123456\0在常量區,p3在棧上。  
    static int c =; //全局(靜态)初始化區 
    p1 = (char *)malloc();  
    p2 = (char*)malloc();*   //配置設定得來的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[];
  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();
           

繼續閱讀