头文件与标准库

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.h

C++ 中仍然可以写 #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输入输出cincout
vector动态数组vector<int>
string字符串string
algorithm常用算法sortreversemax/min
map / set有序容器基于红黑树
unordered_map / unordered_set哈希容器基于哈希表
queue队列/优先队列queuepriority_queue
stackstack
cmath数学函数sqrtpowabs
climits类型极值INT_MAXINT_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++ 代码中函数参数里的 & 符号了。