浅谈 C++ 万能头文件内部头文件
目录
- 引言
- 正文
- 一
- 1 C++ 万能头文件简介
- 2 C++ 万能头文件优点
- 3 C++ 万能头文件缺点
- 二
- 三
- 四
- 五
- 六
- 七
- 八
- 结语
具体内容:
引言:
\(\ \ \ \ \ \ \)本人 OI
萌新,想在洛谷日报上找一些有关 C++
头文件的资料学习,恐惧惊奇地发现竟然找不到。
1
2
3
\(\ \ \ \ \ \ \)于是打开了 C++
的万能头文件,决定自己写一篇博客。
正文:
\(\ \ \ \ \ \ \)打开 C++
的万能头文件,首先映入眼帘的是一堆英文。所以,就请允许我先就此简单介绍一下
C++ 的万能头文件。
\(\ \ \ \ \ \ \)C++ 万能头文件是 GNU
ISO C++ 库中的免费头文件,版权由自由软件基金会(Free Software
Foundation, Inc)所有,其中几乎包含了 C++ 的所有头文件。
\(\ \ \ \ \ \
\)由于这个头文件中几乎包含了 C++
的所有头文件,所以在竞赛中使用这个头文件不仅减少了编写每个需使用的头文件的任务,更节约了比赛的时间。很方便OIer和ACMer的使用。
\(\ \ \ \ \ \
\)首先,因为这个头文件不是 GNU C++
库的标准头文件,所以如果你在一些编译器(除了
GCC)上编译你的代码,可能会导致编译失败,比如 MSVC
上就没有这个头文件。
\(\ \ \ \ \ \
\)其次,由于它包含了很多你的程序并不需要的头文件,会导致编译时间的增加。
\(\ \ \ \ \ \
\)再者,在很多竞赛中,这个头文件是无法使用的,所以,我们不可以一昧地依赖万能头文件,还是要记住一些常用的头文件的。
\(\ \ \ \ \ \
\)再向下翻,是一个这样的注释: \(\ \ \ \ \ \
\)代表下面的一些头文件属于C语言库。
\(\ \ \ \ \ \
\)紧接着,是这样的三行: 1 2 3
| #ifndef _GLIBCXX_NO_ASSERT #include <cassert> #endif
|
\(\ \ \ \ \ \
\)其中,#ifndef
与#endif
属于C语言三种预处理中的条件编译中的一种,这里的意思是:
\(\ \ \ \ \ \
\)如果_GLIBCXX_NO_ASSERT
已被定义,则直接编译#endif
后的语句;如果_GLIBCXX_NO_ASSERT
未被定义,则编译#endif
前的<cassert>
头文件。
\(\ \ \ \ \ \
\)为什么要特意写这三行呢?
\(\ \ \ \ \ \
\)这就涉及到了一种叫“断言”(assert)的东西,“断言”是一种宏,它的原型定义在了这个头文件里。由于断言有时会起到副作用,所以并不是什么时候都要打开的。因此在预先定义了_GLIBCXX_NO_ASSERT
之后,即使使用万能头,断言也不会被打开。
\(\ \ \ \ \ \ \)接下来,就是基本的 C
中的头文件: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| #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>
|
- 五
\(\ \ \ \ \ \
\)在一行的间隔之后,出现了这样的十一行: 1 2 3 4 5 6 7 8 9 10 11
| #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语言三种预处理中的条件编译中的一种,这里的意思是:
\(\ \ \ \ \ \
\)如果#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
之间的这些头文件。
\(\ \ \ \ \ \ \)继续向下:
\(\ \ \ \ \ \
\)代表下面的一些头文件属于C++语言库。
\(\ \ \ \ \ \ \)接下来,就是基本的
C++ 中的头文件: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| #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>
|
- 八
\(\ \ \ \ \ \
\)在一行的间隔之后,出现了这样的二十一行具有版本限制的头文件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| #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
|
\(\ \ \ \ \ \
\)其中#if __cplusplus >= 201103L
和#endif
的作用详见五。
结语:
\(\ \ \ \ \ \ \)本人 OI
萌新,实力有限,本篇博客仅代表个人观点,如有缺漏错误之处,敬请各位大佬斧正。^_^
(结尾附上万能头文件里的所有头文件) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87
| #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
#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
对此文章的重大贡献。
2、有关C++宏的知识详见往期洛谷日报 C++中偷懒利器——宏。
3、参考资料:条件编译_百度百科、assert_百度百科、头文件_百度百科。