C++ 继承了 C 的 #include 机制,但在头文件命名和代码组织上有自己的一套规矩。这篇文章讲讲 C++ 的头文件和 C 有什么不同,using namespace std 是怎么回事,以及刷题党最爱的万能头文件 bits/stdc++.h。
C++ 头文件和 C 的区别
C++ 标准库的头文件没有 .h 后缀,比如输入输出用 iostream 而不是 iostream.h:
// C++ 标准库,没有 .h
#include <iostream>
#include <vector>
#include <algorithm>
// C 标准库在 C++ 中的新名字:去掉 .h,前面加 c
#include <cstdio> // 对应 C 的 stdio.h
#include <cstdlib> // 对应 C 的 stdlib.h
#include <cstring> // 对应 C 的 string.h
#include <cmath> // 对应 C 的 math.hC++ 中仍然可以写 #include <stdio.h>,编译器不会报错。两者的区别是:新写法(cstdio)把函数放进了 std 命名空间,旧写法(stdio.h)把函数放在全局。刷题时用哪种都行,但推荐用 C++ 风格的新写法。
using namespace std 的作用
你可能注意到上面的代码写了一堆 std::。C++ 标准库的所有东西都在 std 命名空间里,每次调用都要加 std:: 前缀。
命名空间是 C++ 用来避免名称冲突的机制。比如你自己定义了一个 sort 函数,不会和标准库的 std::sort 冲突,因为它们在不同的命名空间里。
但刷题时每次都写 std:: 太啰嗦了。加一行 using namespace std 就能省掉所有的 std:: 前缀:
刷题时直接用 using namespace std 就好,方便省事。正式的工程项目中不推荐这样做,因为可能引入名称冲突,但刷题不用操心这个。
刷题常用头文件一览
下面列出刷题中最常用的 C++ 标准库头文件,让你知道"有哪些东西可以用"。具体的用法和示例会在后续的 常用数据结构 和 算法题常用技巧 章节中详细介绍。
| 头文件 | 用途 | 典型内容 |
|---|---|---|
iostream | 输入输出 | cin、cout |
vector | 动态数组 | vector<int> |
string | 字符串 | string |
algorithm | 常用算法 | sort、reverse、max/min |
map / set | 有序容器 | 基于红黑树 |
unordered_map / unordered_set | 哈希容器 | 基于哈希表 |
queue | 队列/优先队列 | queue、priority_queue |
stack | 栈 | stack |
cmath | 数学函数 | sqrt、pow、abs |
climits | 类型极值 | INT_MAX、INT_MIN |
万能头文件 bits/stdc++.h
有一个头文件叫 bits/stdc++.h,它包含了几乎所有的 C++ 标准库头文件。也就是说,你只要 include 这一个文件,所有标准库的功能都能用:
这个头文件在刷题中非常受欢迎,一行代替十几行 include,省心。
不过要注意:bits/stdc++.h 是 GCC 编译器的专属扩展,不是 C++ 标准的一部分。MSVC(Visual Studio)和某些 Clang 环境默认不支持。在本站和大多数 OJ 平台上都能正常使用,但如果你在自己的电脑上编译报错,换成具体的头文件就行。
自定义头文件与多文件组织
和 C 语言一样,C++ 也用头文件来组织多文件项目:
- 头文件(
.h或.hpp):放类定义、函数声明 - 源文件(
.cpp):放函数的具体实现
防止重复包含的写法和 C 一样,用 #ifndef / #define / #endif。C++ 还支持一个更简洁的写法 #pragma once,效果相同:
// math_utils.h
#pragma once
int factorial(int n);
bool isPrime(int n);下面是一个完整的多文件项目示例:
了解了头文件和标准库之后,下一篇我们来讲 函数与引用,学完之后你就能理解 C++ 代码中函数参数里的 & 符号了。