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