刷題-1
1.進程/線程/協程
進程與線程:
- 進程是資源分配的獨立單位,線程是資源調度和分配的最小單位。
- 資源擁有:進程擁有獨立的地址空間。而統一進程下的線程共享地址空間和資源,包括內存/文件句柄等。
- 通信方式:進程通信有特定的機制,比如管道/共享內存/消息隊列/信號等方式。而線程因為內存等資源是共享的,所以可以通過直接讀寫全局變量等就可以通信
- 上下文切換:進程切換的開銷遠大于線程,因為進程切換涉及到了虛擬地址的切換。同樣的道理,進程創建的成本也是遠高于線程的。
- 錯誤影響:得益于內存隔離,單一進程崩潰不會直接影響到其他進程。而線程又可能會對其他線程造成直接影響。
協程
協程可以看作是完全作用在用戶態的線程,主要用于減少成本,提高并發性。
2.堆/棧
- 內存管理:棧內存由操作系統管理分配,而堆為程序員手動分配。
- 數據結構:棧遵循先入后出原則,而堆的結構較復雜多樣。(堆的結構如最大堆/最小堆等也是考察重點!)
- 性能:堆的大小遠大于棧,但棧的訪問速度比堆快很多。
- 服務對象:棧主要儲存局部變量/函數調用/表達式求值,而堆用于動態內存分配/數據持久化/對象存儲等
3.指針/引用
指針是獨立變量/指針可以改變所指地址/大小/指針有多重指針/引用必須初始化,不可為空/
引用通常用于函數傳參,指針用于內存管理和訪問。
4.為什么 析構函數常用虛函數 ?為什么構造函數不虛?
- 析構函數使用虛函數:可以確保資源正確釋放,防止內存泄漏。在多態的情況下,基類指針可以指向派生類對象,析構函數定義為虛函數可以確保刪除對象時正確調用析構函數。
- 構造函數不能定義為虛函數:構造函數的初始化用途使得構造函數不能定義為虛函數。
5.CPP中 多態的實現有哪幾種 ? (靜態 /動態)
- 靜態多態:也叫編譯時多態,主要包括運算符重載和函數重載以及模板。
- 動態多態:也叫運行時多態,包括虛函數和基類指針引用等。
6.new /malloc區別及底層實現原理
new/malloc的區別
- new不僅會分配內存還會調用對象的構造函數,而malloc無構造函數。
- new返回的是對象類型的指針。而malloc默認返回void*類型,一般要進行類型轉換。
- 分配失敗的處理方式不同,new會拋出異常,malloc會返回NULL。
- new是運算符可以被重載,而malloc是庫函數不能被重載。
- new和malloc的底層實現原理不同(見下文)
new/malloc的底層實現
- new的底層機制主要分為兩個部分:分配器和構造器。分配器負責從堆中分配內存,一般會調用第一級的內存管理函數,比如malloc或者由操作系統提供的函數。構造器用來初始化對象,包括調用構造函數,返回地址。
- malloc的底層:小型brk,大型mmap直接映射到地址空間。
7.Struct→CPP內存對齊
內存對齊方式默認由編譯器決定,也可以手動設定。目的是提高內存訪問速度。
- 結構體struct中每個成員變量默認都要對其它的下一位成員補齊,且最末結構體要是最大對齊因子的倍數,話不多說直接上例子。所以這個結構體占用內存為1+(3)+4+8=16,16=2*8,符合要求。
struct MyStruct {
char a; // 占用1字節,后面需要3字節的填充以對齊下一個成員
int b; // 占用4字節
double c; // 占用8字節(在大多數平臺上)
};
8.進程通信
管道/共享內存/消息隊列/信號/套接字

浙公網安備 33010602011771號