浅谈 C++ 万能头文件内部头文件

· · 个人记录

浅谈 C++ 万能头文件内部头文件

(本文为纯原创文章,如要转载,请通知本人并附上出处。)

目录

具体内容:

引言:

![1](https://cdn.luogu.com.cn/upload/image_hosting/t2wlmwpn.png?x-oss-process=image/resize,m_lfit,h_170,w_225) ![2](https://cdn.luogu.com.cn/upload/image_hosting/l6w5b8gy.png?x-oss-process=image/resize,m_lfit,h_170,w_225) ![3](https://cdn.luogu.com.cn/upload/image_hosting/cqmj17wg.png?x-oss-process=image/resize,m_lfit,h_170,w_225) $\ \ \ \ \ \ $于是打开了 C++ 的万能头文件,决定自己写一篇博客。 ------------ ### 正文: - 一 $\ \ \ \ \ \ $打开 C++ 的万能头文件,首先映入眼帘的是一堆英文。所以,就请允许我先就此简单介绍一下 C++ 的万能头文件。 ------------ - 1 C++ 万能头文件简介 $\ \ \ \ \ \ $C++ 万能头文件是 GNU ISO C++ 库中的免费头文件,版权由自由软件基金会(Free Software Foundation, Inc)所有,其中几乎包含了 C++ 的所有头文件。 ------------ - 2 C++ 万能头文件优点 $\ \ \ \ \ \ $由于这个头文件中几乎包含了 C++ 的所有头文件,所以在竞赛中使用这个头文件不仅减少了编写每个需使用的头文件的任务,更节约了比赛的时间。很方便OIer和ACMer的使用。 ------------ - 3 C++ 万能头文件缺点 $\ \ \ \ \ \ $首先,因为这个头文件不是 GNU C++ 库的标准头文件,所以如果你在一些编译器(除了 GCC)上编译你的代码,可能会导致编译失败,比如 MSVC 上就没有这个头文件。 $\ \ \ \ \ \ $其次,由于它包含了很多你的程序并不需要的头文件,会导致编译时间的增加。 $\ \ \ \ \ \ $再者,在很多竞赛中,这个头文件是无法使用的,所以,我们不可以一昧地依赖万能头文件,还是要记住一些常用的头文件的。 ------------ - 二 $\ \ \ \ \ \ $再向下翻,是一个这样的注释: ```cpp // C ``` $\ \ \ \ \ \ $代表下面的一些头文件属于C语言库。 ------------ - 三 $\ \ \ \ \ \ $紧接着,是这样的三行: ```cpp #ifndef _GLIBCXX_NO_ASSERT #include <cassert> //断言 #endif ``` $\ \ \ \ \ \ $其中,`#ifndef`与`#endif`属于C语言三种预处理中的[条件编译](https://baike.baidu.com/item/%E6%9D%A1%E4%BB%B6%E7%BC%96%E8%AF%91)中的一种,这里的意思是: $\ \ \ \ \ \ $如果`_GLIBCXX_NO_ASSERT`已被定义,则直接编译`#endif`后的语句;如果`_GLIBCXX_NO_ASSERT`未被定义,则编译`#endif`前的`<cassert>`头文件。 $\ \ \ \ \ \ $为什么要特意写这三行呢? $\ \ \ \ \ \ $这就涉及到了一种叫“断言”([assert](https://baike.baidu.com/item/assert/10931289#ref_[1]_20093242))的东西,“断言”是一种宏,它的原型定义在了这个头文件里。由于断言有时会起到副作用,所以并不是什么时候都要打开的。因此在预先定义了`_GLIBCXX_NO_ASSERT`之后,即使使用万能头,断言也不会被打开。 ------------ - 四 $\ \ \ \ \ \ $接下来,就是基本的 C 中的头文件: ```cpp #include <cctype> //字符分类函数库 #include <cerrno> //定义错误码 #include <cfloat> //浮点数处理 #include <ciso646> //定义常见运算符的可选拼写 #include <climits> //定义各种数据类型最值常量 #include <clocale> //定义本地化函数 #include <cmath> //定义数学函数 #include <csetjmp> //分别承担非局部标号和 goto 作用 #include <csignal> // 定义了程序执行时如何处理不同的信号 #include <cstdarg> //让函数能够接收可变参数 #include <cstddef> //定义标准宏以及类型 #include <cstdio> //定义输入/输出函数 #include <cstdlib> //定义杂项函数及内存分配函数 #include <cstring> //字符串处理 #include <ctime> //定义关于时间的函数 ``` ------------ - 五 $\ \ \ \ \ \ $在一行的间隔之后,出现了这样的十一行: ```cpp #if __cplusplus >= 201103L #include <ccomplex> //定义复数处理 #include <cfenv> //定义浮点数环境 #include <cinttypes> //提供各种进制的转换宏 #include <cstdalign> //兼容头文件 #include <cstdbool> //定义布尔环境 #include <cstdint> //定义整形环境 #include <ctgmath> //定义常用类型数学宏 #include <cwchar> //定义宽字符串处理函数 #include <cwctype> //定义宽字符串分类、转换函数 #endif ``` $\ \ \ \ \ \ $其中,`#if`与`#endif`也属于C语言三种预处理中的[条件编译](https://baike.baidu.com/item/%E6%9D%A1%E4%BB%B6%E7%BC%96%E8%AF%91)中的一种,这里的意思是: $\ \ \ \ \ \ $如果`#if`后的表达式为真,则编译`#if`与`#endif`之间的这些头文件;如果表达式为假,则直接编译`#endif`后的语句。 $\ \ \ \ \ \ $可能又有人要问了,那`#if`后的语句是什么意思呢? $\ \ \ \ \ \ $为了回答这个问题,我们要先知道`__cplusplus`是个什么东西。 $\ \ \ \ \ \ $`__cplusplus`是 C++ 中的一个宏,被定义为一个整型值,它的值随着 C++ 版本的升高而增大,因此可用于判断 C++ 代码的版本: $\ \ \ \ \ \ $对于 C++98和C++03,`__cplusplus`的值为 199711L。 $\ \ \ \ \ \ $对于 C++11,`__cplusplus`的值为 201103L。 $\ \ \ \ \ \ $对于 C++14,`__cplusplus`的值为 201402L。 $\ \ \ \ \ \ $对于 C++17,`__cplusplus`的值为 201703L。 $\ \ \ \ \ \ $所以,我们就可以很清楚地知道了这个表达式就是在判断你的 C++ 版本,只有版本不低于 C++11,才能编译`#if`与`#endif`之间的这些头文件。 ------------ - 六 $\ \ \ \ \ \ $继续向下: ```cpp // C++ ``` $\ \ \ \ \ \ $代表下面的一些头文件属于C++语言库。 ------------ - 七 $\ \ \ \ \ \ $接下来,就是基本的 C++ 中的头文件: ```cpp #include <algorithm> //STL常用算法 #include <bitset> //STL位集容器 #include <complex> //定义负数类 #include <deque> //STL双端队列容器 #include <exception> //定义异常处理类 #include <fstream> //文件输入输出流 #include <functional> //STL定义运算函数 #include <iomanip> //操纵运算子 #include <ios> //基本输入/输出支持 #include <iosfwd> //输入/输出系统使用的前置声明 #include <iostream> //基本输入输出流 #include <istream> //基本输入流 #include <iterator> //定义迭代器 #include <limits> //定义最值 #include <list> //STL线性列表容器 #include <locale> //定义本地语言环境 #include <map> //STL映射表容器 #include <memory> //定义了用于管理动态内存的常规程序 #include <new> //定义了用于管理动态存储的函数 #include <numeric> //定义了基础性的数值运算 #include <ostream> //基本输出流 #include <queue> //STL队列容器 #include <set> //STL集合容器 #include <sstream> //基于字符串的流 #include <stack> //STL堆栈容器 #include <stdexcept> //定义了一些标准的异常类 #include <streambuf> //底层输入/输出支持 #include <string> //定义字符串类 #include <typeinfo> //定义了一些类型和函数 #include <utility> //STL通用模板类 #include <valarray> //支持面向数值计算的数组 #include <vector> //STL动态数组容器 ``` ------------ - 八 $\ \ \ \ \ \ $在一行的间隔之后,出现了这样的二十一行具有版本限制的头文件: ```cpp #if __cplusplus >= 201103L #include <array> //定义数组 #include <atomic> //定义了原子类型 #include <chrono> //日期和时间库 #include <condition_variable> //定义条件变量 #include <forward_list> //STL单向列表容器 #include <future> //定义 future 类 #include <initializer_list> //定义初始化列表 #include <mutex> //定义互斥锁 #include <random> //随机数库 #include <ratio> //有理数支持 #include <regex> //定义正则表达 #include <scoped_allocator> //定义分配器 #include <system_error> //报告源于操作系统或低层程序接口的错误 #include <thread> //定义 thread 类 #include <tuple> //定义元组 #include <typeindex> //支持 type_index 类及其散列支持 #include <type_traits> //提供模板元基础库 #include <unordered_map> //STL unordered_map 容器 #include <unordered_set> //STL unordered_set 容器 #endif ``` $\ \ \ \ \ \ $其中`#if __cplusplus >= 201103L`和`#endif`的作用详见五。 ------------ ### 结语: $\ \ \ \ \ \ $本人 OI 萌新,实力有限,本篇博客仅代表个人观点,如有缺漏错误之处,敬请各位大佬斧正。^_^ (结尾附上万能头文件里的所有头文件) ```cpp // C #ifndef _GLIBCXX_NO_ASSERT #include <cassert> #endif #include <cctype> #include <cerrno> #include <cfloat> #include <ciso646> #include <climits> #include <clocale> #include <cmath> #include <csetjmp> #include <csignal> #include <cstdarg> #include <cstddef> #include <cstdio> #include <cstdlib> #include <cstring> #include <ctime> #if __cplusplus >= 201103L #include <ccomplex> #include <cfenv> #include <cinttypes> #include <cstdalign> #include <cstdbool> #include <cstdint> #include <ctgmath> #include <cwchar> #include <cwctype> #endif // C++ #include <algorithm> #include <bitset> #include <complex> #include <deque> #include <exception> #include <fstream> #include <functional> #include <iomanip> #include <ios> #include <iosfwd> #include <iostream> #include <istream> #include <iterator> #include <limits> #include <list> #include <locale> #include <map> #include <memory> #include <new> #include <numeric> #include <ostream> #include <queue> #include <set> #include <sstream> #include <stack> #include <stdexcept> #include <streambuf> #include <string> #include <typeinfo> #include <utility> #include <valarray> #include <vector> #if __cplusplus >= 201103L #include <array> #include <atomic> #include <chrono> #include <condition_variable> #include <forward_list> #include <future> #include <initializer_list> #include <mutex> #include <random> #include <ratio> #include <regex> #include <scoped_allocator> #include <system_error> #include <thread> #include <tuple> #include <typeindex> #include <type_traits> #include <unordered_map> #include <unordered_set> #endif ``` ------------ ## 注: 1、特别鸣谢 [@Andysun06](https://www.luogu.com.cn/user/70299) 对此博客的重大贡献。 2、有关C++宏的知识详见往期洛谷日报 [C++中偷懒利器——宏](https://www.luogu.com.cn/blog/Atalod/tou-lan-li-qi-hong)。 3、参考资料:[条件编译_百度百科](https://baike.baidu.com/item/%E6%9D%A1%E4%BB%B6%E7%BC%96%E8%AF%91)、[assert_百度百科](https://baike.baidu.com/item/assert/10931289#ref_[1]_20093242)、[头文件_百度百科](https://baike.baidu.com/item/%E5%A4%B4%E6%96%87%E4%BB%B6)。