一個由c/c++編譯的程序佔用的內存分爲如下幾個部分c++
//----main.cpp---- int a = 0; //全局初始化區 char *p1;// 全局未初始化區 int 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字節的區域就在堆區。 strcpy(p1, "123456"); // 123456\0 放在常量區,編譯器可能會將它與p3所指向的"123456"優化成一個地方。 return 0; }
由系統自動分配。 例如,聲明在函數中一個局部變量 int b; 系統自動在棧中爲b開闢空間程序員
須要程序員本身申請,並指明大小,在c中malloc函數數組
如p1 = (char *)malloc(10);安全
在C++中用new運算符數據結構
如p2 = (char *)malloc(10);函數
可是注意p一、p2自己是在棧中的。優化
只要棧的剩餘空間大於所申請空間,系統將爲程序提供內存,不然將報異常提示棧溢出。spa
首先應該知道操做系統有一個記錄空閒內存地址的鏈表,當系統收到程序的申請時, 會遍歷該鏈表,尋找第一個空間大於所申請空間的堆結點,而後將該結點從空閒結點鏈表中刪除,並將該結點的空間分配給程序,另外,對於大多數系統,會在這塊內存空間中的首地址處記錄本次分配的大小,這樣,代碼中的delete語句才能正確的釋放本內存空間。另外,因爲找到的堆結點的大小不必定正好等於申請的大小,系統會自動的將多餘的那部分從新放入空閒鏈表中。操作系統
在Windows下,棧是向低地址擴展的數據結構,是一塊連續的內存的區域。這句話的意思是棧頂的地址和棧的最大容量是系統預先規定好的,在WINDOWS下,棧的大小是2M(也有的說是1M,總之是一個編譯時就肯定的常數),若是申請的空間超過棧的剩餘空間時,將提示overflow。所以,能從棧得到的空間較小。線程
堆是向高地址擴展的數據結構,是不連續的內存區域。這是因爲系統是用鏈表來存儲的空閒內存地址的,天然是不連續的,而鏈表的遍歷方向是由低地址向高地址。堆的大小受限於計算機系統中有效的虛擬內存。因而可知,堆得到的空間比較靈活,也比較大。 申請效率的比較: 棧由系統自動分配,速度較快。但程序員是沒法控制的。 堆是由new分配的內存,通常速度比較慢,並且容易產生內存碎片,不過用起來最方便。
____________________________________________________________________
當要建立一個對象時,首選棧,效率遠超在堆上建立。
若是這個對象會做爲返回值傳出去,能夠考慮改函數,把返回值改爲一個指針參數,在外部棧建立後傳進來;若是由於各類緣由,不行就堆建立吧。
當要建立一個變長數組,強烈建議想個MAX而後棧建立,不建議直接堆建立(有時候就是3個和8個的區別),不放心就判斷一下大於MAX,特殊處理。
當在類中使用多態的成員時,沒辦法,堆建立吧,你也能夠開闢最大可能的大小而後棧建立,但何須呢,那是語言要解決的問題。
若是是要建立被不少人引用的一個對象,你放在棧上可能安全也可能生命期太短,那就別惹這個麻煩,乖乖強制堆建立吧,畢竟c/c++的指針/引用沒有生命期分析,你引用了失效的東西也不報錯的。
跨線程共享一個對象,堆建立吧,跟上面理由差很少。
一句話概述,生命期簡單的用棧,就算是變長,只要變得不離譜仍是用棧,其它的用堆吧。