(1)刷題第一彈

寒柏懒得想發表於2024-11-01

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.程序通訊

管道/共享記憶體/訊息佇列/訊號/套接字

9.const/ static關鍵字

10.智慧指標△

11.怎麼保證執行緒安全

12.常見處理雜湊衝突的方法

13.深複製和淺複製

14.左值引用和右值引用

15.單例模式及CPP實現

相關文章