C++堆記憶體,棧記憶體,new,不new之間的關係梳理
阿新 • • 發佈:2018-12-29
一、一個由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();