C++ 常用头文件

在 C++ 中,标准库提供了丰富的现成类型与函数,它们按功能存放在不同的头文件中。平时写代码时,很多小伙伴常会遇到一个很实际的问题:明明知道要使用哪个工具,却拿不准顶部应该包含哪个头文件。

其实,数量众多的标准库头文件完全不需要死记硬背。下面我们将日常开发最常用的头文件按功能整理成了分类速查表,大家写代码拿不准时随时回来按表查阅即可。

包含头文件的 2 个基本原则

在查阅具体的分类表格之前,我们先明确关于 #include 预处理命令的 2 个基本原则:

  • 用到什么,就显式包含什么:有时只写了 #include <iostream> 没写 #include <string>,std::string 碰巧也能编译通过,这是因为部分编译器的头文件内部存在间接包含。但不同编译环境的内部依赖随时可能变化,我们用到了哪个工具,就应该显式包含它对应的头文件。
  • 包含头文件不等于省掉 std:: 前缀:比如 #include <vector> 只是把相关声明引入当前源文件,而标准库的名称依然定义在 std 这个独立的命名空间中,我们使用时仍然要写全 std::vector。

下面我们来看一个组合包含多个标准库头文件的例子。

示例:组合包含多个头文件

#include <algorithm>
#include <iostream>
#include <vector>

int main() {
    std::vector<int> nums = {30, 10, 20};    // 来自 <vector>
    std::sort(nums.begin(), nums.end());     // 来自 <algorithm>

    for (int n : nums) {
        std::cout << n << ' ';               // 来自 <iostream>
    }
    std::cout << '\n';
    return 0;
}

运行结果如下。

10 20 30

分析:

在这个例子中,#include <algorithm>、#include <iostream> 和 #include <vector> 分别引入了排序函数 std::sort()、输出流 std::cout 以及动态数组 std::vector 所在的头文件。

平时如果我们写对了 std::sort 或 std::vector,编译时却报错提示 'xxx' is not a member of 'std',意思是在 std 中找不到该名称,多半就是顶部漏写了对应的头文件。养成按需包含并按字母顺序排列头文件的习惯,能让代码的依赖关系一目了然。

输入输出与字符串头文件

控制台输入输出、本地文件读写以及字符串处理是日常编程中出现频率最高的操作,对应的标准库头文件如下表所示。

输入输出与字符串头文件
头文件 常用类型与函数 主要用途与说明
<iostream> std::cin、std::cout、std::cerr 标准控制台输入与输出流
<iomanip> std::setw()、std::setprecision()、std::fixed 控制输出宽度、对齐方式与小数位数
<fstream> std::ifstream、std::ofstream、std::fstream 本地普通文件与二进制文件的读写
<sstream> std::stringstream、std::istringstream 在内存中进行字符串流的拼接与解析
<string> std::string、std::getline()、std::to_string() 现代字符串类、整行读取与数值互转
<string_view> std::string_view 轻量只读字符串视图(C++17 起)
<format> std::format() 使用 {} 占位符格式化字符串(C++20 起)
<print> std::print()、std::println() 直接向控制台格式化输出文本(C++23 起)
<cctype> std::isalpha()、std::isdigit()、std::toupper() 单个字符的类别判断与大小写转换
<cstring> std::strlen()、std::strcpy()、std::strcmp() 操作以 '\0' 结尾的 C 风格字符数组

在这组头文件中,初学的小伙伴最容易搞混的是 <string> 和 <cstring>。在现代 C++ 开发中,处理日常文本优先使用 <string> 提供的 std::string 类,而 <cstring> 则是为了兼容 C 风格字符串准备的工具头文件。

STL 容器、迭代器与算法头文件

STL 容器负责在内存中组织和保存数据,迭代器与算法则负责获取序列范围并执行排序、查找、去重或累加等操作。对应的标准库头文件如下表所示。

容器、迭代器与算法头文件
头文件 常用类型与函数 主要用途与说明
<vector> std::vector 支持在尾部快速动态增删的连续数组容器
<array> std::array 长度在编译期固定的现代数组容器(C++11 起)
<deque> std::deque 支持首尾两端快速增删的双端队列容器
<list> std::list 支持任意位置快速插删的双向链表容器
<set> / <unordered_set> std::set、std::unordered_set 自动去重的有序集合与哈希集合
<map> / <unordered_map> std::map、std::unordered_map 存放键值对的有序映射表与哈希表
<stack> std::stack 遵循后进先出(LIFO)规则的栈容器适配器
<queue> std::queue、std::priority_queue 先进先出普通队列与按优先级出队的优先队列
<iterator> std::size()、std::begin()、std::end() 获取数组元素个数及通用的容器首尾迭代器
<algorithm> std::sort()、std::find()、std::reverse() 等 排序、查找、二分、反转与去重等通用算法
<numeric> std::accumulate()、std::gcd()、std::lcm() 序列累加求和、最大公约数与最小公倍数
<ranges> std::views::filter、std::views::transform 管道式范围视图与按需序列转换(C++20 起)

在 C++ 中,STL 容器的头文件非常好记,基本都与容器本身同名。比如使用 std::vector 就包含 <vector>,使用 std::map 就包含 <map>。只有优先队列 std::priority_queue 是个例外,它和普通队列一起存放在 <queue> 头文件中。

而在遍历与算法方面,查询原生数组长度的 std::size() 位于 <iterator> 中。像排序、查找这类常用的 STL 算法以及 std::ranges::sort 等范围算法都集中在 <algorithm> 中,只有 std::accumulate()、std::gcd() 等偏数值计算的算法放在 <numeric> 头文件中。

内存管理与实用工具头文件

当我们需要使用智能指针管理动态内存,或者使用键值对、函数包装器以及现代可选值类型时,对应的标准库头文件如下表所示。

内存与实用工具头文件
头文件 常用类型与函数 主要用途与说明
<cstddef> std::size_t、std::nullptr_t 表示大小或下标的无符号整型与空指针类型
<memory> std::unique_ptr、std::shared_ptr、std::make_unique() 智能指针与动态内存自动管理
<utility> std::pair、std::move()、std::swap() 键值对结构、移动语义转换与变量交换
<tuple> std::tuple、std::make_tuple()、std::get() 可打包任意数量、不同类型元素的元组
<functional> std::function、std::greater<> 通用函数包装器与标准比较函数对象
<optional> std::optional、std::nullopt 表达 “有值” 或 “无值” 的可选值包装(C++17 起)
<variant> std::variant、std::get()、std::visit() 类型安全的现代联合体容器(C++17 起)
<span> std::span 连续内存序列的观察视图(C++20 起)
<concepts> std::integral、std::floating_point 等 模板参数的编译期概念约束(C++20 起)
<compare> std::strong_ordering、operator<=> 三路比较运算符与比较结果类型(C++20 起)

在这一组头文件中,小伙伴们最容易找错位置的是 std::pair、std::move() 和 std::swap()。这三个高频工具既不在提供 std::unique_ptr 等智能指针的 <memory> 里,也不在 <algorithm> 里,而是统一存放在 <utility> 通用工具头文件中。

此外,日常表示容器长度或数组下标的 std::size_t 正式定义在 <cstddef> 中,而用来包装普通函数与 Lambda 表达式的 std::function 则位于 <functional> 头文件中。

文件、时间、数学与异常头文件

在涉及目录路径操作、高精度时间测量、常见数学计算、随机数生成以及异常错误处理时,对应的标准库头文件如下表所示。

文件、时间、数学与异常头文件
头文件 常用类型与函数 主要用途与说明
<filesystem> std::filesystem::path、exists()、copy_file() 跨平台文件路径解析与目录操作(C++17 起)
<chrono> std::chrono::system_clock、steady_clock、duration 高精度时钟、时间戳获取与耗时计算
<cmath> std::abs()、std::pow()、std::sqrt()、std::round() 绝对值、幂运算、开方与取整等数学函数
<random> std::mt19937、std::uniform_int_distribution 现代随机数生成引擎与概率分布器
<limits> std::numeric_limits 查询各种数值类型的最大值与最小值范围
<exception> std::exception 所有标准库异常类的共同基类
<stdexcept> std::runtime_error、std::out_of_range 等 日常可直接抛出或捕获的具体标准异常类
<cassert> assert() 运行期调试断言宏,条件不成立时终止程序

在使用标准异常时,我们要留意区分两个容易混淆的头文件:顶层基类 std::exception 位于 <exception> 中,而日常直接用来抛出或捕获具体错误的 std::runtime_error、std::out_of_range 等异常类则位于 <stdexcept> 头文件中。

C 兼容头文件的命名规律

细心的小伙伴可能会发现,C++ 标准库头文件都不带 .h 后缀,但其中有一小部分专门以字母 c 开头,比如 <cmath>、<cstring>、<cctype>、<cassert> 和 <cstddef>。

其实,它们都是从 C 语言的 <math.h>、<string.h> 等头文件改造而来的兼容版本:去掉末尾的 .h,在最前面加上字母 c,并将里面的函数统一放进 std 命名空间。编写现代 C++ 代码时,我们推荐统一包含 <cmath>、<cstring>,不要再混用旧式的 .h 头文件。

多线程与并发编程头文件

如果我们需要在程序中创建并发线程、执行互斥加锁、条件等待或异步任务,对应的 5 个标准并发头文件如下表所示。

多线程与并发头文件
头文件 常用类型与函数 主要用途与说明
<thread> std::thread、std::this_thread::sleep_for() 创建并管理并发执行线程及线程休眠延时
<mutex> std::mutex、std::lock_guard、std::unique_lock 互斥锁及基于 RAII 的自动加锁与解锁守卫
<condition_variable> std::condition_variable 实现多线程之间的条件等待与通知唤醒
<atomic> std::atomic 提供无锁、线程安全的原子变量读写操作
<future> std::async()、std::future、std::promise 启动异步任务并获取异步计算的返回值

这 5 个头文件都是从 C++11 起正式加入标准库的,我们使用多线程开发并发功能时可以直接跨平台编译。如果在 Linux 系统下使用 g++ 编译包含 <thread> 或 <future> 的代码时遇到链接报错,记得在编译命令中加上 -pthread 参数。

常见问题

1. 刷算法题时常说的 “万能头文件” bits/stdc++.h,在实际项目开发中能用吗?

不推荐在实际项目中使用。<bits/stdc++.h> 并不是 C++ 官方标准规定的头文件,而是 GCC 编译器内部提供的一个非标准文件,它会一次性把几乎所有标准库头文件全部包含进来。

如果我们在代码里写了它,切换到 Visual Studio(MSVC)等环境就会直接报 “找不到头文件” 错误,无法跨平台编译,而且还会明显拖慢项目的编译速度。在正式项目开发中,大家都应该养成 “用到哪个就包含哪个” 的规范习惯。

2. #include 后面的尖括号 <> 和双引号 "" 有什么区别?

它们决定了编译器去哪里查找头文件,平时遵循下面两条规则即可:

尖括号 <>:直接去系统标准库目录和已配置的第三方库目录查找,所有 C++ 标准库头文件统一使用尖括号,比如 #include <iostream>。

双引号 "":优先在当前源文件所在的项目文件夹中查找,专门用来包含我们自己编写的项目头文件,比如 #include "student.h"。

上一篇:

下一篇: 没有了

给站长反馈

绿叶网正在不断完善中,小伙伴们如果发现任何问题,还望多多给站长反馈,谢谢!

邮箱:lvyenet@vip.qq.com

「绿叶网」服务号
绿叶网服务号放大
关注服务号,微信也能看教程。
绿叶网服务号