主要面的是C++,過後總結下吧~~有些答案結合了網上的“標准答案”給出的。。嘻嘻,不是抄襲,是借鑒哦~~
1.談談你對C++內存分配的理解
1.1 還是的先看看C++對內存分為哪幾個區?
1、棧區(stack)— 由編譯器自動分配釋放 ,存放函數的參數值,局部變量的值等。其操作方式類似於數據結構中的棧。想知道為什麼效率高嗎?因為關於棧的操作如push集成在處理器的指令集中,效率很高,但是分配的內存容量有限。
2、堆區(heap) — 一般由程序員分配釋放, 若程序員不釋放,程序結束時可能由OS回收 。注意它與數據結構中的堆是兩回事,分配方式倒是類似於鏈表。
3、全局區(靜態區)(static)—,全局變量和靜態變量的存儲是放在一塊的,初始化的全局變量和靜態變量在一塊區域, 未初始化的全局變量和未初始化的靜態變量在相鄰的另一塊區域。
4、文字常量區—常量字符串就是放在這裡的。
5、程序代碼區—存放函數體的二進制代碼。
1.2 再給面試官談談new/delete和malloc/free的區別?
1、像我們的new/delete和malloc/free就是在上面所說的堆區上操作。程序員申請了內存,用完要記得釋放,否則就內存洩露了。而且多次申請釋放,會造成堆區碎片,這個需要注意下。
2、new/delete是操作符,而malloc/free是函數。前者可以被重載。前者可以有構造函數和析構函數。前者返回的某種類型對象的指針,後者返回VOID指針。
2.基於問題1,深入談談堆和棧
1、申請方式:
棧:函數內的局部變量:int a = 10;
堆:new / malloc
2、申請後的系統響應:
棧:只要申請的空間大小<棧的剩余空間,棧就分配。
堆:因為new,malloc都是C++封裝的,裡面做了這樣的事:首先明白windows有這麼一個記錄空閒空間地址的鏈表,C++遍歷該鏈表,先找到第一個空閒空間大小大於程序員申請的空間大小的地址(堆節點),將該堆節點從鏈表中刪除,把該節點的空間分配給程序。對於大多數系統,會在這塊內存空間中的首地址處記錄本次分配的大小,這樣,代碼中的delete語句才能正確的釋放本內存空間。由於找到的堆結點的大小不一定正好等於申請的大小,系統會自動的將多余的那部分重新放入空閒鏈表中。
3、申請大小:
棧:默認是1M?還是2M?
堆:看系統的虛擬內存有多大了。(請記住堆是一個節點為空閒內存空間的鏈表。。)堆是向高地址擴展的數據結構,是不連續的內存區域。這是由於系統是用鏈表來存儲的空閒內存地址的,自然是不連續的,而鏈表的遍歷方向是由低地址向高地址。堆的大小受限於計算機系統中有效的虛擬內存。由此可見,堆獲得的空間比較靈活,也比較大。
4、申請效率:
棧:速度快,push,pop等指令都內置在處理器了,能不快嗎?
堆:相對慢(為什麼慢,可以看2,就知道它在申請的時候干了多少事),還容易產生內存碎片。不過容量大,操作方便。
5、存儲內容:
棧(依次是):
主函數中後的下一條指令地址
然後是函數的各個參數(在大多數的C編譯器中,參數是由右往左入棧的)
函數中的局部變量
堆:程序員隨意安排。
6、存取效率:
先看看這段代碼:
int main(){
char a = 1;
char c[] = "1234567890";
char *p ="1234567890";
a = c[1];
a = p[1];
return 0;
}
這是在函數內,char數組c,是在棧上。
char *p = "1234567890" ,其中雖然*p也是在棧上,但是"1234567890"在常量區。
再看看它們對應的匯編代碼:
10: a = c[1];
00401067 8A 4D F1 mov cl,byte ptr [ebp-0Fh]
0040106A 88 4D FC mov byte ptr [ebp-4],cl
11: a = p[1];
0040106D 8B 55 EC mov edx,dword ptr [ebp-14h]
00401070 8A 42 01 mov al,byte ptr [edx+1]
00401073 88 45 FC mov byte ptr [ebp-4],al
可以看到在棧上的c[]只要兩行就能取到內容,而p要先去把常量區的內容放到edx中,再存取。
說明純棧操作,效率是要高一些的。
7、總結
看看一個經典代碼就什麼都懂了:
//main.cpp
int a = 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字節的區域就在堆區。
strcpy(p1, "123456"); //123456\0放在常量區,編譯器可能會將它與p3所指向的"123456"優化成一個地方。
}
更多詳情見請繼續閱讀下一頁的精彩內容: http://www.linuxidc.com/Linux/2014-11/109161p2.htm
《C++ 設計新思維》 下載見 http://www.linuxidc.com/Linux/2014-07/104850.htm
C++ Primer Plus 第6版 中文版 清晰有書簽PDF+源代碼 http://www.linuxidc.com/Linux/2014-05/101227.htm
讀C++ Primer 之構造函數陷阱 http://www.linuxidc.com/Linux/2011-08/40176.htm
讀C++ Primer 之智能指針 http://www.linuxidc.com/Linux/2011-08/40177.htm
讀C++ Primer 之句柄類 http://www.linuxidc.com/Linux/2011-08/40175.htm
將C語言梳理一下,分布在以下10個章節中: