基礎語言特性
IO 流與條件判斷
- `while (cin >> x)`:流對象轉為 `bool` 判斷狀態,EOF 或錯誤時為 `false`
- VS 中未初始化指針無法輸出;`string`/`int` 未初始化在 VS 為編譯錯誤
- C++ 推薦 `nullptr` 替代 `NULL`/`0` 作為空指針
- `void*` 只能比較、傳遞、賦值給 `void*`,不能直接解引用操作
引用與指針進階
- `T*&`:指針的引用,函數內修改指針本身可影響實參
- `const T&` 綁定字面值/臨時對象/不同類型(產生臨時量)
- `constexpr` 指針初始值只能是 `nullptr`/`0`/固定地址對象
- 函數體內變量非常量表達式,`constexpr` 指針不能指向它
類型推導
| 表達式 | auto 推導 | decltype 推導 |
| `int i = 42` | `int` | `int` |
| `const int ci = 42` | `int` (忽略頂層 const) | `const int` |
| `int& r = i` | `int` | `int&` |
| `const int& cr = i` | `int` | `const int&` |
| `int arr[10]` | `int*` | `int[10]` |
| `int* p = arr` | `int*` | `int*` |
| `decltype((i))` | - | `int&` (雙層括號→引用) |
字符串與容器操作
- `getline` 遇換行符結束,即使開頭是換行也返回空串
- 字符串字面值與 `std::string` 是不同類型,`+` 運算至少一方為 `string`
- 範圍 `for` 內不得改變容器大小(迭代器失效)
- `vector::operator[]` 只能訪問已有元素,不能添加
- 迭代器 `end()` 不可解引用/遞增;`difference_type` 為帶符號距離類型
- `forward_list` 不支持遞減、`push_back`、`pop_back`
數組與指針
- C++ 無真正多維數組,「多維」實為數組的數組
- `size_t` 定義於 ``,無符號,用於下標/大小
- 指針相減得 `ptrdiff_t`(帶符號),同屬 ``
- 尾後指針不可解引用/遞增
- `char a[] = "Hello"` 含結束符,`char* p = "Hello"` 指向只讀字面值
- `typedef` 只能為類型別名,數組類型別名需用 `using Arr = int[4];`
函數與重載
- 局部靜態對象:首次經過定義初始化,程序結束銷毀
- 引用形參優於指針;不需修改用 `const T&`
- `initializer_list` 元素均為 `const`
- `void` 函數 `return expr;` 要求 `expr` 也是 `void` 函數調用
- 含 `return` 的循環後必須有 `return`,否則未定義行為
- 不返回局部對象的引用/指針
- 默認實參:從右向左連續,後續聲明只能補全無默認值的參數
- `inline` 僅是建議,編譯器可忽略
- `constexpr` 函數:字面值類型參數/返回,單一 `return`,編譯期可計算
- 函數指針類型必須完全匹配;`decltype(func)` 得函數類型非指針
類設計核心
封裝與訪問控制
- `struct` 默認 `public`,`class` 默認 `private`,唯一區別
- 友元聲明只影響訪問權限,非普通聲明,需額外在類外聲明才能被調用
- 類內類型定義需前置,通常放類開頭
- 類內初始值只能用 `=` 或 `{}` 形式
- `mutable` 允許 `const` 成員函數修改該成員
構造函數
- 構造函數不能 `const`;`const` 對象構造完成後才具備常量性
- 內置/復合類型成員無類內初始值 → 僅適合合成默認構造函數
- `= default` 在類內為 `inline`,類外非 `inline`
- 初始化列表順序 = 成員聲明順序,與列表書寫順序無關
- 委托構造函數:`C(int x) : C(x, 0) {}`
- 默認構造函數使用場景:塊作用域無初始化定義、類成員無初始化、數組初始化不足、局部靜態無初始化
隱式轉換與 explicit
- 單參數構造函數定義隱式轉換規則
- 只允許一步類類型轉換
- `explicit` 抑制隱式轉換,僅允許直接初始化
- 顯式轉換:`static_cast(expr)`、`T(expr)`
靜態成員
- 靜態數據成員:類外定義初始化,屬於類不屬於對象
- `constexpr static` 類內初始化,若用於不可替換場景仍需類外定義
- 靜態成員函數:無 `this`,不能 `const`,不能訪問非靜態成員
- 靜態成員可作為默認實參
IO 流深度
- 流有緩衝區:`flush` 刷新,`ends` 輸出 `\0` 並刷新,`endl` 輸出 `\n` 並刷新
- `unitbuf` 模式:每次輸出後自動 `flush`
- 程序崩潰緩衝區不刷新 → 數據丟失
- `ofstream` 保留原文件需指定 `app` 或 `in` 模式
STL 容器與算法精要
容器操作失效規則
| 操作 | vector/string | deque | list/forward_list | 關聯容器 |
| 插入 | 全部失效 | 全部失效 | 不失效 | 不失效 |
| 刪除 | 刪除點後失效 | 全部失效 | 僅被刪除失效 | 僅被刪除失效 |
| swap | 失效 | 不失效 | 不失效 | 不失效 |
關鍵算法分類
- 非變序:`count`、`find`、`search`、`equal`、`mismatch`、`lexicographical_compare`
- 變序:`copy`、`replace`、`remove`、`fill`、`generate`、`transform`、`sort`、`partition`、`binary_search`
- `stable_sort` 保證相等元素相對順序
- `unique` 僅移除相鄰重複,需配合 `sort`
- 關聯容器不適用泛型算法(迭代器為 `const`)
Lambda 表達式
- 捕獲列表:`[=]` 值捕獲,`[&]` 引用捕獲,`[x, &y]` 混合
- 值捕獲在創建時拷貝,引用捕獲需保證生命週期
- `mutable` 允許修改值捕獲的副本
- 泛型 Lambda (C++14):`[](auto a, auto b) { return a + b; }`
智能指針與動態內存
- `unique_ptr`:獨佔所有權,不可拷貝,可移動,`make_unique` (C++14)
- `shared_ptr`:共享所有權,引用計數,`make_shared` 一次分配控制塊+對象
- `weak_ptr`:弱引用,打破循環引用,`lock()` 獲取 `shared_ptr`
- `get()` 僅用於傳遞裸指針給不接管所有權的代碼,絕不用於初始化另一個智能指針
- `new (nothrow) T` 失敗返回 `nullptr` 不拋異常
- 刪除數組必須 `delete[]`,單對象 `delete`,混用導致未定義行為
拷貝控制與資源管理
- 五大特殊成員:構造、拷貝構造、移動構造、拷貝賦值、移動賦值、析構
- 拷貝構造第一參數必須是 `const T&`
- 需要析構函數的類通常需要拷貝/移動操作(三/五法則)
- `= default` 顯式要求編譯器生成合成版本
- `= delete` 禁用特定操作(如禁止拷貝)
- 移動操作應 `noexcept`,且處理自賦值
模板進階
- 模板參數:類型參數、非類型參數 (整型/指針/引用)、模板模板參數
- 類模板實參推導 (C++17):`std::pair p(1, 2.0);` 自動推導為 `pair`
- 模板特化:全特化、偏特化(類模板)
- SFINAE:`std::enable_if`、表達式檢測控制重載解析
- 可變參數模板:`template void f(Args... args)` + 折疊表達式 (C++17)
並發與線程 (C++11+)
- `std::thread`、`std::mutex`、`std::lock_guard`/`unique_lock`、`std::condition_variable`
- `std::async` + `std::future` 異步任務
- `std::atomic` 無鎖原子操作
- `thread_local` 線程局部存儲
- 內存模型:`memory_order` 控制可見性與順序
現代 C++ 最佳實踐清單
- 優先 `const`、`constexpr`、`auto`、`nullptr`、`範圍 for`
- RAII 管理所有資源:智能指針、容器、鎖守衛
- 值語義優先,移動語義優化,避免裸 `new/delete`
- 介面設計:傳值/傳常引用/轉移所有權(`unique_ptr`/`T&&`)
- 算法優於手寫循環:``、``
- 錯誤處理:異常用於不可恢復錯誤,`std::optional`/`expected` (C++23) 用於可恢復錯誤
- 編譯期計算:`constexpr`、`if constexpr` (C++17)、概念 (C++20)
- 模塊化:命名空間、模塊 (C++20)、頭文件護衛
總結
這份筆記提煉了 C++ Primer 核心知識體系:從基礎類型推導、類設計、模板機制,到 STL 容器/算法特性、智能指針資源管理、現代 C++ 語法糖與最佳實踐。掌握「值類別語義、RAII、移動優化、編譯期計算、標準庫優先」這條主線,配合對未定義行為邊界的敬畏,是寫出高效、安全、可維護 C++ 代碼的關鍵。