程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> 關於C++ >> c說話stack(棧)和heap(堆)的應用詳解

c說話stack(棧)和heap(堆)的應用詳解

編輯:關於C++

c說話stack(棧)和heap(堆)的應用詳解。本站提示廣大學習愛好者:(c說話stack(棧)和heap(堆)的應用詳解)文章只能為提供參考,不一定能成為您想要的結果。以下是c說話stack(棧)和heap(堆)的應用詳解正文


1、准備常識—法式的內存分派

一個由C/C++編譯的法式占用的內存分為以下幾個部門

1、棧區(stack)—由編譯器主動分派釋放,寄存函數的參數值,部分變量的值等。其操作方法相似於數據構造中的棧。
2、堆區(heap)—普通由法式員分派釋放,若法式員不釋放,法式停止時能夠由OS收受接管。留意它與數據構造中的堆是兩回事,分派方法卻是相似於鏈表。
3、全局區(靜態區)(static)—全局變量和靜態變量的存儲是放在一塊的,初始化的全局變量和靜態變量在一塊區域,未初始化的全局變量和未初始化的靜態變量在相鄰的另外一塊區域。法式停止後由體系釋放。
4、文字常量區—常量字符串就是放在這裡的。法式停止後由體系釋放。
5、法式代碼區—寄存函數體的二進制代碼。

2、例子法式

//main.cpp
 int a=0;  //全局初始化區
 char *p1;  //全局未初始化區
 main()
 {
  intb;棧
  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"優化成一個處所。
}

3、堆和棧的實際常識
2.1請求方法
stack:
由體系主動分派。例如,聲明在函數中一個部分變量int b;體系主動在棧中為b開拓空間

heap:
 須要法式員本身請求,並指明年夜小,在c頂用malloc函數
如p1=(char*)malloc(10);
在C++頂用new運算符
如p2=(char*)malloc(10);
然則留意p1、p2自己是在棧中的。

2.2請求後體系的呼應
棧:只需棧的殘剩空間年夜於所請求空間,體系將為法式供給內存,不然將報異常提醒棧溢出。
堆:起首應當曉得操作體系有一個記載余暇內存地址的鏈表,當體系收到法式的請求時,會遍歷該鏈表,尋覓第一個空間年夜於所請求空間的堆結點,然後將該結點從余暇結點鏈表中刪除,並將該結點的空間分派給法式,別的,關於年夜多半體系,會在這塊內存空間中的首地址處記載本次分派的年夜小,如許,代碼中的delete語句能力准確的釋放本內存空間。別的,因為找到的堆結點的年夜小紛歧定正好等於請求的年夜小,體系會主動的將過剩的那部門從新放入余暇鏈表中。

2.3請求年夜小的限制
棧:在Windows下,棧是向低地址擴大的數據構造,是一塊持續的內存的區域。這句話的意思是棧頂的地址和棧的最年夜容量是體系事後劃定好的,在WINDOWS下,棧的年夜小是2M(也有的說是1M,總之是一個 編譯時就肯定的常數),假如請求的空間跨越棧的殘剩空間時,將提醒overflow。是以,能從棧取得的空間較小。
堆:堆是向窪地址擴大的數據構造,是不持續的內存區域。這是因為體系是用鏈表來存儲余暇內存地址的,天然是不持續的,而鏈表的遍歷偏向是由低地址向窪地址。堆的年夜小受限於盤算機體系中有用的虛擬內存。因而可知,堆取得的空間比擬靈巧,也比擬年夜。

2.4請求效力的比擬:
棧:由體系主動分派,速度較快。但法式員是沒法掌握的。
堆:是由new分派的內存,普通速度比擬慢,並且輕易發生內存碎片,不外用起來最便利。別的,在WINDOWS下,最好的方法是用Virtual Alloc分派內存,他不是在堆,也不是在棧,而是直接在過程的地址空間中保存一塊內存,固然用起來最不便利。然則速度快,也最靈巧。

2.5堆和棧中的存儲內容
棧:在函數挪用時,第一個進棧的是主函數中後的下一條指令(函數挪用語句的下一條可履行語句)的地址,然後是函數的各個參數,在年夜多半的C編譯器中,參數是由右往左入棧的,然後是函數中的部分變量。留意靜態變量是不入棧的。當本次函數挪用停止後,部分變量先出棧,然後是參數,最初棧頂指針指向最開端存的地址,也就是主函數中的下一條指令,法式由該點持續運轉。
堆:普通是在堆的頭部用一個字節寄存堆的年夜小。堆中的詳細內容由法式員支配。

2.6存取效力的比擬


char s1[]="aaaaaaaaaaaaaaa";
char *s2="bbbbbbbbbbbbbbbbb";
aaaaaaaaaaa是在運轉時辰賦值的;而bbbbbbbbbbb是在編譯時就肯定的;然則,在今後的存取中,在棧上的數組比指針所指向的字符串(例如堆)快。好比:
#include
int main()
{
char a=1;
char c[]="1234567890";
char *p="1234567890";
a = c[1];
a = p[1];
return 1;
}

對應的匯編代碼

10:a=c[1];
004010678A4DF1movcl,byteptr[ebp-0Fh]
0040106A884DFCmovbyteptr[ebp-4],cl
11:a=p[1];
0040106D8B55ECmovedx,dwordptr[ebp-14h]
004010708A4201moval,byteptr[edx+1]
004010738845FCmovbyteptr[ebp-4],al

第一種在讀取時直接就把字符串中的元素讀到存放器cl中,而第二種則要先把指針值讀到edx中,在依據edx讀取字符,明顯慢了。
2.7小結
堆和棧的差別可以用以下的比方來看出:應用棧就象我們去飯店裡吃飯,盡管點菜(收回請求)、付錢、和吃(應用),吃飽了就走,不用理睬切菜、洗菜等預備任務和洗碗、刷鍋等收尾任務,他的利益是快捷,然則自在度小。應用堆就象是本身著手做愛好吃的菜肴,比擬費事,然則比擬相符本身的口胃,並且自在度年夜。

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