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.程序通訊
管道/共享記憶體/訊息佇列/訊號/套接字