C++ 速查 — 簡明參考
C++17/20 語法、標準庫、類、模板與最常用慣用法速查手冊,覆蓋約 80% 日常場景。
C++ C++17 / C++20
ISO C++ (GCC / Clang / MSVC) · 多範式(OOP · 泛型 · 函數式) · 靜態 · 強類型 · 名義類型
學習路徑
先跟着「Hello World 與構建環境」跑通編譯流程 → 熟悉變量、類型、流程控制與函數 → 用標準庫容器(vector/map)與字符串 → 理解 RAII 與智能指針(mem 節)→ 再看 OOP 與模板 → 最後按需查線程、網絡、正則與構建調試。FAQ 節適合回頭避坑。
1.Hello World 與構建環境
從零開始編譯、運行並組織一個 C++ 程序:工具鏈、命令行參數、多文件與 C++20 模塊。
最小程序
每個 C++ 程序從 main() 開始執行,返回 0 表示成功。std::cout 是標準輸出流,用 << 送入內容。
編譯與運行
用 g++ 或 clang++ 編譯:-std 指定 C++ 標準版本,-Wall -Wextra 開啓警告,-o 指定輸出文件名,再 ./app 運行。
CMake 構建
CMake 是跨平台主流構建系統:CMakeLists.txt 聲明項目與目標,-B 指定構建目錄,--build 編譯,產物在 build/ 下。
命令行參數
main 的 argc 是參數個數,argv 是參數字符串數組,argv[0] 恆為程序名。程序從 argv[1] 開始讀取用户參數。
退出碼
main 的返回值傳給操作系統作為進程退出碼:0 表示成功,非 0 表示錯誤類別。用 EXIT_SUCCESS / EXIT_FAILURE 更可讀。
多文件編譯
聲明放頭文件(#pragma once 防重複包含),定義放 .cpp,使用處 #include。編譯時把各 .cpp 一起傳給編譯器鏈接。
C++20 模塊
模塊替代頭文件:export module 聲明模塊、export 導出符號、import 導入,編譯更快、無宏污染,但仍處推廣期。
命名空間
命名空間組織符號避免衝突。用命名空間限定(geo::area)訪問;using namespace 一次引入全部符號易產生歧義,優先 using std::cout 精確引入。
2.變量與常量
聲明與類型推導、const/constexpr、引用、結構化綁定、作用域與 C++ 風格類型轉換。
auto 類型推導
auto 根據初始化器推導類型,必須立即初始化。推導會去掉引用與頂層 const,需要時顯式寫 const auto&。
const 與 constexpr
const 表示值不可變;constexpr 保證編譯期求值,可用於數組大小、模板參數。C++20 後 constexpr 函數可含更多邏輯。
引用
引用是已存在對象的別名:聲明必須初始化、永遠指向同一對象。作參數傳引用可避免拷貝並允許修改原值。
結構化綁定
C++17 把 pair/tuple/結構體/數組解包成命名變量。map 迭代裏解包 key/value 是最常用場景。
內聯變量
C++17 前頭文件裏的非 constexpr 全局變量會引發重複定義錯誤;inline 變量允許多個編譯單元共享同一對象。
mutable 成員
const 成員函數中也能修改 mutable 成員,典型用於緩存、調用計數、互斥鎖等「邏輯上不改變對象」的狀態。
decltype
decltype 取表達式的聲明類型。decltype((x)) 加括號推導為引用,是常見陷阱;後置返回類型常用於模板函數。
作用域與遮蔽
C++ 支持塊作用域遮蔽外層同名變量。避免遮蔽全局名 —— 用 ::n 可顯式訪問全局,但可讀性差。
字面量後綴
後綴指定字面量類型:LL 長整型、f 浮點、s 轉 std::string。0b 二進制前綴與 ' 數字分隔符提升可讀性。
C++ 風格轉換
static_cast 編譯期語義轉換;dynamic_cast 運行期多態轉換(指針失敗返 nullptr、引用拋 bad_cast);const_cast 去除 const 須確保原對象非 const。
3.數據類型
內置類型、枚舉、結構體、模板類型與 std::optional/variant/any 等現代工具類型。
內置類型
內置類型按大小與有無符號區分。<cstdint> 提供定寬類型 int32_t/uint64_t,跨平台行為一致。
枚舉類
enum class 比裸 enum 更安全:值必須用作用域限定訪問,且不會隱式轉 int,避免名字泄漏與整型誤用。
結構體
struct 默認成員公有,適合打包無行為的數據。帶默認值的成員可用花括號聚合初始化一行建好對象。
聯合體
union 讓多個成員共享同一塊內存、同一時刻只保存一個。標準 C++ 用 std::variant 更安全,union 一般只用於底層內存複用。
模板類型
模板把類型參數化,編譯器按用到的類型生成對應實例,是泛型編程與標準庫容器的基礎。
類型別名
using 聲明類型別名比 typedef 更清晰且能定義模板別名。別名不產生新類型,只是同類型的另一個名字。
optional 可選值
std::optional 表達「可能有值也可能沒有」的返回值,替代哨兵值或 out 參數。上下文布爾判斷檢查存在性,* 取內容。
variant 類型聯合
std::variant 是類型安全的聯合體,任一時刻持有類型列表中的一個。std::get 取指定類型(不符拋 bad_variant_access),std::get_if 返回指針不拋異常。
any 任意類型
std::any 可存任意類型,運行時再取回。適合異構容器或插件傳參,但有類型擦除開銷,儘量用 variant。
pair 與 tuple
pair 存兩個值、tuple 存任意多個。結構化綁定把元素解包成命名變量,比 std::get 按索引取更可讀。
4.指針與數組
裸指針、智能指針、數組與引用 —— 誰擁有內存、何時用哪一種。
裸指針
裸指針存對象的地址,* 解引用、& 取地址。裸指針不擁有內存,需要配對 new/delete 或交給智能指針。
指針與數組
數組名在表達式中退化為指向首元素的指針,p+i 是地址偏移、*(p+i) 取值。這是繼承自 C 的底層行為。
nullptr 空指針
nullptr 是類型安全的空指針常量,替代 NULL 或 0。解引用空指針是未定義行為,使用前務必判空。
new 與 delete
new 分配堆內存並返回指針,delete 釋放;new[] 必須配 delete[]。手動管理易泄漏,優先 RAII 容器或智能指針。
unique_ptr 獨佔指針
unique_ptr 獨佔所有權,離開作用域自動 delete。make_unique 異常安全;轉移所有權用 std::move,複製被禁止。
shared_ptr 共享指針
shared_ptr 引用計數共享所有權,計數歸零才釋放。避免循環引用導致泄漏 —— 用 weak_ptr 打破環。
weak_ptr 弱引用
weak_ptr 不擁有對象、不影響計數,lock() 臨時提升為 shared_ptr(對象已釋放則返回空)。專用於打破循環引用。
引用 vs 指針
引用語法更直接且保證非空,作參數優先用引用;需要「可能無對象」或「要重新指向別處」時用指針。
const 指針
讀法從右往左:int* const 指針本身不可變、const int* 所指不可變。混用是最常見的聲明混淆點。
void* 指針
void* 是「指向未知類型內存」的指針,必須顯式轉換回具體類型才能解引用。C 風格 API 用它傳任意數據,C++ 裏儘量避免。
5.流程控制
if/for/while/switch 與 C++17 起 if/switch 的初始化語句。
if / else
if/else 按條件選擇執行路徑。C++17 起 if 可帶初始化語句(見 if-init)。
for 循環
經典 for 由初始化、條件、步進三段組成。計數循環優先用 ++i,語義上減少一次臨時拷貝。
範圍 for
範圍 for(C++11)遍歷容器元素,避免手寫下標與邊界錯誤。需要改元素用 auto&,只讀用 const auto&。
while / do-while
while 先判斷條件再進入循環體;do-while 至少執行一次。適合循環次數未知、依賴運行期條件的場景。
switch / case
switch 按整型/枚舉值分發,比 if 鏈更清晰。每個 case 必須 break(或 return),否則會貫穿落到下一分支。
break 與 continue
continue 跳過本輪剩餘代碼進入下一輪;break 立刻退出整個循環。雙層循環裏可用標籤跳外層。
if 初始化語句
C++17 起 if/switch 可聲明初始化變量,作用域限制在分支內,避免變量泄漏到外層,是 find+check 的慣用寫法。
三元運算符
三元運算符一行表達 if/else 賦值。兩個分支類型須兼容;邏輯複雜時寫 if 更可讀。
goto 標籤
goto 直接跳到標籤行,破壞結構化控制流,幾乎總能用 flag 或 return 替代。唯一合理場景是跳出多層嵌套循環。
6.函數與 Lambda
聲明與定義、重載、傳參、lambda 與函數模板、變參模板與遞歸。
聲明與定義
聲明告訴編譯器簽名,定義提供實現。聲明可放頭文件多次包含不報錯,定義每個程序只能有一份。
函數重載
函數重載讓同名函數按實參類型分派,編譯器選最匹配版本。不可僅靠返回類型區分重載。
默認參數
默認參數讓調用方省略尾部實參。默認值只能從最右側開始連續提供;聲明與定義只能一處給默認值。
傳參方式
按值傳參拷貝整個對象;按 const& 傳避免拷貝且不可改;按 & 可改原值;&&(右值引用)接收臨時對象以便轉移資源。
返回值
現代 C++ 返回臨時值靠返回值優化(RVO/NRVO)零拷貝。絕不要返回局部對象的地址或引用(懸垂)。
Lambda 表達式
lambda 是匿名函數對象:[] 捕獲列表 + 參數 + 函數體。配合 <algorithm> 是寫回調、比較器的主流方式。
Lambda 捕獲
[=] 按值捕獲全部、[&] 按引用捕獲全部,[x] 捕獲指定變量。捕獲引用時要保證原變量在 lambda 存活期間有效。
函數模板
函數模板按調用實參推導類型生成實例,一個實現服務所有類型。類型必須支持用到的運算符。
變參模板
參數包 ...Args 接收任意數量實參,摺疊表達式 (args + ...) 用二元運算符展開,是 printf 式自定義函數的新式替代。
遞歸
遞歸是函數調用自身,基準條件結束遞歸。深遞歸消耗調用棧,注意棧溢出與重複計算的優化。
7.字符串
std::string 基礎、拼接、查找替換、格式化、字符串流與數值互轉。
std::string 基礎
std::string 是可變、可增長的字符容器,內存自動管理。[] 下標越界未定義,用 at() 會拋異常。
字符串字面量
"..." 字面量默認是 const char*;加 s 後綴轉 std::string;string_view 是隻讀非擁有視圖,作參數避免拷貝。
拼接與預分配
大量拼接時用 reserve 預分配減少內存重分配。多個 + 會產生臨時對象,熱點代碼注意複用緩衝區。
子串與查找
substr(pos, len) 取子串;find/rfind 找首個匹配位置,找不到返回 std::string::npos。
替換
成員 replace(pos, len, str) 按位置替換;<algorithm> 的 std::replace 按值批量替換所有匹配字符。
格式化輸出
std::format(C++20)按佔位符格式化,編譯期檢查參數個數,替代 sprintf 與 cout 拼接。:04d 補零、:.2f 保留兩位小數。
字符串流
stringstream 把內存字符串當流用:ostringstream 拼接、istringstream 按 >> 解析,格式化與反解析的靈活工具。
字符串與數值互轉
stoi/stod/stoll 把字符串解析為數值,std::to_string 反向轉換。解析失敗或溢出會拋 std::invalid_argument/out_of_range。
原始字符串
R"(...)" 原始字符串內反斜槓不做轉義,寫正則、路徑、多行文本免去轉義噩夢。內容含 )" 時用 R"tag(...)tag"。
遍歷字符
範圍 for 逐字符遍歷最簡潔;需要修改用 char&。begin/end 迭代器方式兼容舊代碼與算法庫。
8.容器與算法
vector/array/map/set/優先隊列與排序、查找、ranges 算法。
vector 動態數組
vector 是動態數組,尾部增刪 O(1)、隨機訪問 O(1)。頻繁 push_back 用 reserve 預留容量;不要頭部插入(O(n))。
std::array 定長數組
std::array 是棧上定長數組的現代封裝:有 size()/begin()/end(),可參與算法庫。定長用 array,變長用 vector。
map 有序字典
std::map 是有序鍵值對(紅黑樹),按鍵排序、查找 O(log n)。不排序時用 unordered_map(平均 O(1))。
unordered_map 哈希表
unordered_map 哈希表,平均 O(1) 查找、無序。注意 operator[] 對不存在鍵會插入零值,只查詢用 find 或 at()。
set 集合
set 存有序去重集合,insert/erase/find 均 O(log n);unordered_set 是哈希版本(無序、O(1))。contains()(C++20)判存在。
deque 與 list
deque 雙端隊列頭尾 O(1);list 鏈表中間插入 O(1) 但隨機訪問 O(n)。容器選擇看訪問模式。
優先隊列(堆)
priority_queue 是堆:push O(log n)、top 取最值 O(1)。默認最大堆;最小堆需指定 greater 比較器。
排序
std::sort 隨機訪問容器原地排序 O(n log n)。自定義比較器返回「a 是否排在 b 前」。list 用成員 sort()。
查找
無序集合用 std::find 線性查找;已排序容器用 binary_search/lower_bound 二分 O(log n)。find 返回迭代器,用 != end() 判斷命中。
ranges 管道視圖
C++20 ranges 用 | 管道組合惰性視圖:filter 過濾、transform 映射,不拷貝、不分配,表達式式處理序列。
9.動態內存與所有權
RAII、移動語義、智能指針的取捨與異常安全 —— C++ 資源管理的核心。
RAII 資源獲取即初始化
RAII 把資源的獲取放在構造函數、釋放放在析構函數,對象銷燬時自動釋放,異常安全、無需顯式清理。
make_unique
make_unique 構造 unique_ptr,new+構造一步完成,即使構造拋異常也不泄漏裸指針。數組版本 make_unique<T[]>(n)。
make_shared
make_shared 一次分配對象與控制塊,比 new 再包 shared_ptr 少一次分配。C++20 起控制塊不浪費對象大小對齊。
移動語義
std::move 把左值轉成右值引用,觸發移動而非拷貝 —— 轉移內部指針、源對象被置空,避免深拷貝大數組。
移動構造
移動構造竊取源對象資源並把源置空,比拷貝快。聲明為 noexcept 便於 vector 擴容時用移動而非拷貝。
返回值優化
編譯器省略多餘的拷貝/移動構造,返回值直接構造到目標。C++17 起保證按值返回的臨時對象零拷貝。
打破循環引用
父子樹裏父持 shared_ptr、子回指父用 weak_ptr,否則互相持有永不釋放。lock() 臨時提升驗證對象存活。
noexcept 承諾
noexcept 聲明函數不拋異常,是 vector 擴容選用移動構造的依據。承諾後實際拋出會 std::terminate 終止程序,不確定時別寫。
手動管理的泄漏
手動 new/delete 遇到中途異常或提前 return 就會泄漏。RAII(智能指針/容器)把清理交給析構,異常安全。
10.面向對象
類、訪問控制、構造與析構、繼承多態、純虛接口、友元與運算符重載。
類定義
class 把數據與操作封裝在一起。成員默認私有(與 struct 相反),通過公有方法訪問私有數據。
訪問限定符
public 公開、protected 派生可見、private 僅自身。默認 class 私有、struct 公有。
構造函數
構造函數與類同名,用初始化列表 : x(x_) 初始化成員(比函數體賦值更高效)。無參數版本稱默認構造。
委託構造
委託構造讓一個構造函數調用同類另一個構造,避免重複初始化邏輯。被委託者必須已聲明。
析構函數
析構函數在對象銷燬時執行,是 RAII 釋放資源的地方。基類析構必須 virtual,否則 delete 派生類時只析構基類部分。
繼承
繼承讓派生類複用基類接口與實現。通過基類指針/引用調用 virtual 函數發生運行時多態分派。
虛函數與抽象類
virtual 聲明可重寫函數,純虛(=0)使類成為抽象類不可實例化。含 virtual 的類析構也應 virtual。
override 與 final
override 聲明「我確實在重寫基類虛函數」,簽名不匹配會編譯報錯而不是靜默新建函數;final 禁止進一步重寫。
純虛接口
純虛函數 = 0 定義接口不提供實現,含純虛的類是抽象類,派生類必須實現才能實例化。類似 Java 的 interface。
友元
friend 允許指定類或函數訪問私有成員,打破封裝。應謹慎用於緊密耦合場景(運算符重載、內部迭代器)。
運算符重載
運算符重載讓自定義類型支持 + - << 等語法。保持直覺語義:+ 不修改操作數、<< 是輸出。濫用降低可讀性。
11.錯誤處理
異常捕獲、標準異常層級、自定義異常、noexcept 與 optional/expected 的無異常路徑。
try / catch
try 塊內拋出的異常被 catch 捕獲。優先捕獲 std::exception& 基類,必要時按具體類型分 catch;不捕獲則沿調用棧傳播。
按引用捕獲
按 const& 捕獲保留多態類型且零拷貝;按值捕獲會切片(派生異常被截斷成基類)。catch(...) 捕獲一切但拿不到信息。
標準異常層級
標準異常繼承自 std::exception。特定類型分支放前面、std::exception& 兜底放最後,按最具體優先匹配。
自定義異常
自定義異常繼承 std::runtime_error(或其兄弟),用 using 繼承構造函數,what() 已帶消息,捕獲時按基類捕獲即可。
noexcept 與異常
noexcept 承諾不拋異常,vector 擴容、move 時依賴它。實際拋出會 std::terminate 直接終止程序,不確定時別寫。
optional 表達失敗
對「預期可能失敗」的操作返回 std::optional 比拋異常更輕量,調用方顯式處理無值分支。異常留給意外錯誤。
expected 攜帶錯誤
std::expected(C++23)同時攜帶值或錯誤描述,比 optional 多帶錯誤信息、比異常更可預測,適合解析校驗類代碼。
異常安全
異常安全靠 RAII:把清理放進局部對象的析構,無論正常返回還是拋異常都執行,避免資源泄漏或狀態不一致。
errno 與 C 交互
errno 是 C 時代的全局錯誤碼,被下一個失敗調用覆蓋且線程不安全。C++ 優先用異常,errno 僅與 C 函數交互時立即讀取。
12.文件與流 I/O
讀寫文件、逐行讀取、格式化輸出、filesystem 路徑與二進制文件。
寫入文件
ofstream 打開文件寫入,<< 格式化輸出。析構時自動關閉;顯式 close() 能儘早捕獲寫入失敗。默認覆蓋已存在文件。
讀取文件
ifstream 打開文件讀取,getline 逐行讀入。循環條件是 getline 的返回值:讀到 EOF 或失敗時結束。
讀行 vs 讀詞
getline 讀整行、>> 讀單個詞並跳過空白。混用時 >> 後殘留的換行需 ignore() 清掉,否則 getline 讀到空串。
格式化控制
<iomanip> 的 setw/setprecision/fixed 控制輸出格式,列寬對齊與小數位控制在打印表格時常用。
內存流落盤
ostringstream 先在內存拼好再一次性寫入文件,避免多次磁盤 IO;解析輸入先用 istringstream 校驗。
filesystem 目錄
<filesystem>(C++17)處理路徑與目錄:exists/create_directories/遍歷。比字符串拼路徑更健壯,分隔符自動適配。
路徑分解
fs::path 處理路徑分解與拼接,跨平台自動用正確分隔符。filename/extension/parent_path 取路徑組成部分。
二進制文件
二進制模式 std::ios::binary 不轉換換行符,write/read 按字節塊讀寫。結構體寫盤注意內存對齊與端序兼容。
標準輸入校驗
cin >> 失敗會把流置為 fail,之後所有讀取失效。clear() 清狀態、ignore() 丟髒數據後再繼續。讀取後總是校驗 cin 狀態。
13.常見坑
十組 C++ 經典反例(BAD)與正解(GOOD)—— 紅綠配色,逐條對照。
有符號無符號混算
有符號與無符號混合比較時,有符號自動轉無符號,-1 變成巨大無符號數。比較前顯式轉換或統一符號。
返回懸垂引用
返回局部變量的引用或指針是懸垂引用,函數返回後內存失效,使用是未定義行為。返回值或提升對象生命週期。
基類析構非 virtual
通過基類指針 delete 派生對象時,基類析構必須 virtual,否則派生部分的析構不執行、資源泄漏。
整數除法取整
兩個整數相除結果仍是整數(截斷),賦值給 double 前就丟了小數。至少把一邊轉浮點再除。
循環拼接字符串
s = s + x 每次拷貝整個已有串生成新臨時對象,O(n²);reserve + += 就地追加為 O(n)。大數據量拼接性能差一個量級。
using namespace std
頭文件裏 using namespace std 讓每個包含它的文件暴露全部 std 符號,產生歧義。精確 using 或直接 std:: 限定。
i++ 還是 ++i
i++ 返回舊值(需要拷貝/臨時),++i 直接遞增。對 int 無差別,但自定義類型/迭代器上 ++i 少一次拷貝。
const 正確性
只讀參數用 const&,語義自文檔且避免拷貝。const 正確性讓編譯器幫你攔下誤改,也讓調用方知道函數不改參數。
宏代替函數
宏不參與類型檢查、不遵守作用域、易產生副作用重複求值。能寫 const/constexpr 函數或模板就優先。
循環按值拷貝
範圍 for 按值會拷貝每個元素;大對象用 const auto& 只讀、auto& 修改。數據小且需要副本時才按值。
14.線程與併發
std::thread、互斥鎖、原子操作、條件變量與異步任務。
創建線程
std::thread 創建新線程執行可調用對象(函數/lambda)。線程對象銷燬時必須已 join 或 detach,否則 std::terminate。
join 與 detach
join 阻塞當前線程等子線程結束;detach 讓子線程獨立運行,分離後無法再 join,且其訪問的對象須保持存活。
mutex 互斥鎖
mutex 互斥鎖保護共享數據,同一時刻只允許一個線程持有。手動 lock/unlock 易遺漏,優先 lock_guard/unique_lock。
lock_guard 自動加鎖
lock_guard 用 RAII 管理鎖:構造加鎖、析構解鎖,任何退出路徑(含異常)都保證解鎖,是加鎖的標準方式。
原子操作
std::atomic 對基本類型提供原子操作,多線程下免鎖修改。fetch_add/load/store 都是原子操作,比互斥鎖開銷小。
條件變量
condition_variable 讓線程等待條件:wait 釋放鎖並阻塞、notify 喚醒。wait 必須帶謂詞防虛假喚醒。
async / future
std::async 啓動異步任務返回 future,get() 阻塞取結果。比手寫 thread+共享變量簡單;可指定 launch::async 強制新線程。
thread_local
thread_local 變量每個線程一份獨立副本,天然免鎖緩存、計數、臨時狀態。線程結束銷燬,適合線程私有數據。
數據競爭
兩個線程同時讀寫同一非原子變量是數據競爭(未定義行為,結果不可預測)。用 atomic 或 mutex 同步。
並行算法
C++17 <execution> 給算法加執行策略:par 並行、unseq 向量化。大數據量自動利用多核,前提是元素無共享可變狀態。
15.網絡(Socket)
POSIX socket 創建、監聽、連接、收發與超時控制(跨平台網絡建議用 Boost.Asio 或 libcurl)。
創建套接字
POSIX socket 是網絡 I/O 底基:socket() 創建套接字,AF_INET IPv4、SOCK_STREAM TCP。返回文件描述符,-1 表示失敗。
綁定與監聽
bind 把套接字綁定到端口,listen 開始監聽。htons 把主機字節序轉網絡字節序。sockaddr_in 是 IPv4 地址結構。
accept 接受連接
accept 取出隊列中的客户端連接返回新套接字,每個連接一個 fd。原監聽 fd 繼續 accept 下一個連接。
客户端連接
客户端 socket()+connect() 連到服務器地址。inet_pton 把點分十進制 IP 轉二進制地址。connect 失敗返回 -1。
發送與接收
send/recv 在 TCP 套接字上收發字節。recv 返回 0 説明對端關閉、-1 是錯誤。TCP 是流式協議,需自定報文邊界。
域名解析
getaddrinfo 把主機名+服務解析成可 connect 的地址鏈表,自動處理 IPv4/IPv6。替代手寫 inet_pton+端口的推薦方式。
超時控制
SO_RCVTIMEO 給 recv 設超時,超時返回 -1 且 errno=EWOULDBLOCK。阻塞式 recv 因此變得可控,避免永久掛死。
極簡 HTTP 請求
HTTP 請求是文本協議:請求行 + 頭 + 空行。演示直接發 socket 報文;生產環境優先用 libcurl(自動處理重定向、TLS、壓縮)。
16.時間與日期
chrono 的 duration / time_point、兩種時鐘、格式化、睡眠與耗時測量。
duration 時長
duration 表示時間長度,類型攜帶單位:seconds/milliseconds/microseconds。字面量後綴 s/ms/us 直觀,duration_cast 跨單位轉換。
time_point 時刻
time_point 是時間軸上的某個時刻,由時鐘+duration 偏移組成。時間點加減 duration 得到新時刻,兩個時刻相減得 duration。
system_clock
system_clock 對應系統牆鍾,可與 time_t 互轉(to_time_t/from_time_t),用於展示日曆時間、日誌時間戳。受系統改時影響。
steady_clock
steady_clock 單調遞增、不受系統時間調整影響,是計時基準(測耗時、超時判斷)。展示日曆時間才用 system_clock。
格式化時間
put_time 按 strftime 格式把 time_t 格式化成本地時間字符串。%Y-%m-%d %H:%M:%S 最常用。localtime 返回靜態緩衝區、非線程安全。
線程睡眠
sleep_for 睡指定時長,sleep_until 睡到指定時刻。阻塞當前線程,主線程睡眠會凍結 UI,只在後台/測試用。
測量耗時
計時慣例:start 記起點、結束減起點得 duration、duration_cast 換算單位再 count() 取值。steady_clock 保證不受改時影響。
C 風格時間互轉
time_t 是秒級時間戳,gmtime 轉 UTC 結構、localtime 轉本地結構,strftime 格式化。注意這些函數用靜態緩衝區、非線程安全。
時區
C++20 的 zoned_time 帶時區輸出時間,自動處理夏令時。舊標準庫無時區,需依賴系統 localtime 或第三方庫。
17.進程與信號
system、fork/exec/wait 子進程、環境變量、信號處理與管道取輸出(POSIX 概念)。
system 執行命令
system() 調用 shell 執行字符串命令,簡單但不安全(命令注入、shell 差異)。需要捕獲輸出或參數時用 fork+exec 或 popen。
fork 複製進程
fork 複製當前進程為子進程,返回兩次:父進程得子 pid、子進程得 0。-1 表示失敗。fork 後子進程從 fork 處繼續執行。
exec 替換程序
exec 系列在當前進程內加載新程序替換自身。fork+exec 組合啓動外部命令。exec 成功不返回、失敗返回 -1,子進程要處理失敗路徑。
wait 等待子進程
waitpid 等待指定子進程結束並取退出狀態。WIFEXITED 判斷正常退出、WEXITSTATUS 取退出碼。不 wait 的子進程會變殭屍進程。
環境變量
getenv 讀環境變量(不存在返回 nullptr)、setenv 設置、unsetenv 刪除。環境變量是父進程傳給子進程的簡單配置通道。
信號處理
signal 註冊信號處理器,SIGINT(Ctrl+C)、SIGTERM(kill 默認)等。信號處理函數中只能做異步安全操作,別用堆分配/IO。
sigaction 可靠信號
sigaction 比 signal 更可靠:可設信號屏蔽與標誌。SA_RESTART 讓被信號中斷的阻塞調用自動恢復。生產代碼優先 sigaction。
exit 與 _exit
exit 終止進程並運行 atexit 清理函數、刷新緩衝;_exit 直接終止不清理。fork 後的子進程應 _exit 避免重複清理父資源。
popen 管道取輸出
popen 執行命令並管道讀其輸出("r" 讀 / "w" 寫輸入),比 system 能捕獲輸出。pclose 關閉並等待,返回值含退出狀態。
18.正則表達式
std::regex 的匹配、搜索、替換、捕獲組、標誌與原始字符串寫法。
基礎匹配
std::regex 默認用 ECMAScript 語法。regex_match 要求整個字符串匹配、regex_search 找子串。R"()" 原始字符串免轉義。
整體匹配與分組
regex_search 找第一個匹配子串,smatch 保存整體(m[0])與捕獲組(m[1]…)。regex_match 要求整串匹配、適合校驗格式。
遍歷所有匹配
循環 regex_search 從上一匹配的結尾繼續,遍歷所有匹配。m.suffix().first 是匹配後剩餘部分起點。或直接用 regex_iterator。
替換
regex_replace 全局替換所有匹配。替換模板裏 $& 是整段匹配、$1 引用捕獲組。需要按位置替換時用 regex_iterator。
迭代器批量提取
sregex_iterator 把「找所有匹配」封裝成迭代器,遍歷即得所有結果,比手寫 while regex_search 簡潔,適合批量提取。
捕獲組
捕獲組用圓括號分組,smatch 按下標訪問。(?:...) 是非捕獲組只做邏輯分組不佔編號。命名組 (?<name>...) 用 m["name"]。
匹配標誌
std::regex 構造器第二參數是標誌:icase 忽略大小寫、multiline 讓 ^/$ 匹配行首尾、ECMAScript/extended 選語法方言。多個用 | 組合。
原始字符串寫正則
R"(...)" 裏反斜槓原樣保留,寫正則與路徑不轉義。帶 )" 的串用 R"tag(...)tag" 自定義定界。始終優先原始字符串寫正則。
正則異常
非法正則表達式在構造時拋 std::regex_error,捕獲它避免程序崩潰。高代價編譯的正則可複用對象避免每次重編。
19.構建與調試
編譯標誌、Makefile / CMake、格式化、sanitizer、調試器與性能分析。
常用編譯標誌
常用標誌:-std 選標準、-O 優化級別、-g 調試信息、-Wall -Wextra 警告、-Werror 警告即錯誤。多文件先 -c 分編譯再鏈接。
Makefile
Makefile 聲明目標與依賴,make 按依賴自動重編。$< 第一個依賴、$@ 目標、$^ 全部依賴。規則行必須 Tab 縮進。
CMake
CMake 聲明式構建,跨平台生成 Makefile/VS 工程。target_link_libraries 鏈接庫,find_package 找依賴。構建在獨立 build/ 目錄。
pkg-config 查庫參數
pkg-config 查詢庫的編譯/鏈接參數,$(pkg-config ...) 命令替換注入命令行,避免手寫路徑。鏈接第三方庫的標準方式。
clang-format 格式化
clang-format 自動格式化代碼,.clang-format 文件統一風格。ColumnLimit 控制行寬、SortIncludes 排序頭文件。提交前跑一遍保持一致。
Sanitizer 檢測
編譯期加 sanitizer 在運行期捕獲內存/併發錯誤:address 查越界泄漏、undefined 查未定義行為、thread 查數據競爭。測試必開。
gdb 調試器
gdb 是命令行調試器,-g 編譯註入符號。break 斷點、run 啓動、bt 看棧、print 查值。UI 調試器(VSCode/CLion)底層也是它。
valgrind 內存檢測
valgrind 檢測運行期內存問題:未初始化讀、越界、泄漏、雙釋放。--leak-check=full 輸出每個泄漏的調用棧。速度慢,跑測試子集即可。
靜態庫打包
ar 把多個 .o 打包成靜態庫 lib*.a,-L 指定庫目錄、-l 指定庫名(省略 lib 前綴與 .a 後綴)。靜態庫打進可執行文件、無運行時依賴。
性能分析
gprof/perf 剖析熱點函數。g++ -pg 注入採樣、運行後 gprof 輸出每個函數的調用次數與耗時佔比,定位優化熱點。
關於本速查
本頁是 C++17/C++20 的自包含速查手冊,覆蓋語言核心、標準模板庫(STL)與構建工具鏈在真實項目中約 80% 的常見用法。內容偏向現代慣用法:智能指針(unique_ptr / shared_ptr)、移動語義、auto 類型推導、範圍 for、結構化綁定,以及 C++20 的 concepts 與 ranges。C++ 由 Bjarne Stroustrup 於 1985 年創建,兼具 C 的高性能與高層抽象能力,是系統編程、遊戲引擎與高性能計算領域的基石語言。 19 個章節各自聚焦一個主題:基礎語法、變量、類型與指針、控制流、函數、字符串、集合、內存管理、面向對象、錯誤處理、輸入輸出、常見誤區、併發、網絡、時間、進程、正則與構建工具。每個小節都配有「概念介紹 + 可直接複製的代碼片段」,方便查閲與實驗。 所有代碼與文字均在瀏覽器本地渲染,無任何數據離開你的設備。權威參考見 cppreference 與 ISO C++ 標準草案。
版本 2.1.0