在Windows操作系统下,由操作系统分配的内存就叫做堆
?
堆(Heap) 上面的工作是編譯器做的,即程序員并不參與堆棧的維護。但上面已經說了,堆棧相當于在編譯時期分配內存,因此一旦計算好某塊內存的偏移,則這塊內存就只能那么大,不能變化了(如果變化會導致其他內存塊的偏移錯誤)。比如要求客戶輸入定單數據,可能有10份定單,也可能有100份定單,如果一開始就定好了內存大小,則可能造成不必要的浪費,又或者內存不夠。
?
為了解決上面的問題,C++提供了另一個途徑,即允許程序員有兩種向操作系統申請內存的方式。前一種就是在棧上分配,申請的內存大小固定不變。后一種是在堆上分配,申請的內存大小可以在運行的時候變化,不是固定不變的。
?
那么什么叫堆?在Windows操作系統下,由操作系統分配的內存就叫做堆,而棧可以認為是在程序開始時就分配的堆(這并不準確,但為了不復雜化問題,故如此說明)。因此在堆上就可以分配大小變化的內存塊,因為是運行時期即時分配的內存,而不是編譯時期已計算好大小的內存塊。
?
變量的定義
?
上面說了那么多,你可能看得很暈,畢竟連一個實例都沒有,全是文字,下面就來幫助加深對上面的理解。
?
定義一個變量,就是向上面說的由編譯器維護的變量表中添加元素,其語法如下:
?
long a;
?
先寫變量的類型,然后一個或多個空格或制表符(\t)或其它間隔符,接著變量的名字,最后用分號結束。要同時定義多個變量,則各變量間使用逗號隔開,如下:
?
long a, b, c; unsigned short e, a_34c;
?
上面是兩條變量定義語句,各語句間用分號隔開,而各同類型變量間用逗號隔開。而前面的式子5+2/3-5*2,則如下書寫。
?
long a = 2/3, b = 5*2; long c = 5 + a – b;
?
可以不用再去記那煩人的地址了,只需記著a、b這種簡單的標識符。當然,上面的式子不一定非要那么寫,也可以寫成:long c = 5 + 2 / 3 – 5 * 2; 而那些a、b等中間變量編譯器會自動生成并使用(實際中編譯器由于優化的原因將直接計算出結果,而不會生成實際的計算代碼)。
?
下面就是問題的關鍵,定義變量就是添加一個映射。前面已經說了,這個映射是將變量名和一個地址關聯,因此在定義一個變量時,編譯器為了能將變量名和某個地址對應起來,幫程序員在前面提到的棧上分配了一塊內存,大小就視這個變量類型的大小。如上面的a、b、c的大小都是4個字節,而e、a_34c的大小都是2個字節。
?
假設編譯器分配的棧在一開始時的地址是1000,并假設變量a所對應的地址是1000-56,則b所對應的地址就是1000-60,而c所對應的就是1000-64,e對應的是1000-66,a_34c是1000-68。如果這時b突然不想是4字節了,而希望是8字節,則后續的c、e、a_34c都將由于還是原來的偏移位置而使用了錯誤的內存,這也就是為什么棧上分配的內存必須是固定大小。
?
考慮前面說的紅色文字:“變量實際并不是一塊內存,只是一個映射元素”。可是只要定義一個變量,就會相應地得到一塊內存,為什么不說變量就是一塊內存?上面定義變量時之所以會分配一塊內存是因為變量是一個映射元素,需要一個對應地址,因此才在棧上分配了一塊內存,并將其地址記錄到變量表中。但是變量是可以有別名的,即另一個名字。這個說法是不準確的,應該是變量所對應的內存塊有另一個名字,而不止是這個變量的名字。
轉載于:https://blog.51cto.com/lailjiaaie/881431
總結
以上是生活随笔為你收集整理的在Windows操作系统下,由操作系统分配的内存就叫做堆的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 怎么样减肚子最快最有效
- 下一篇: [转] MySQL主从复制(Master