• C++ 头文件与常用函数

    专为算法刷题设计的头文件使用指南 - 避坑版

    目录


    输入输出流 iostream

    是什么

    C++标准输入输出库,提供cin、cout、endl等对象进行格式化输入输出。

    怎么用

    为什么用

    常见陷阱与注意事项

    1. cin读取字符串遇到空格会停止

    2. cin和getline混用的坑

    3. 加速IO后不能混用scanf/printf

    4. endl vs '\n'

    5. 读取到文件末尾

    6. 浮点数输出精度

    7. 终极性能封印:解除 cin/cout 的同步限制(防 TLE)

    在默认情况下,cin/coutscanf/printf 慢非常多。因为 C++ 为了保证混合输入输出时的兼容性,强制把 cin/cout 和 C 语言的 stdio 缓冲区绑定在了一起。在遇到百万级别的数据输入时,不关同步必然超时(Time Limit Exceeded)。

    ✅ 考场必备的加速咒语(写在 main 函数第一行):

    ⚠️ 致命陷阱: 加了这三行代码后,绝对不能再在代码中混用 scanf/printf/puts!否则缓冲区的剥离会导致输入输出顺序彻底错乱。

    补充:scanf/printf格式化(更快)


    动态数组 vector

    是什么

    动态大小的数组,自动管理内存,是STL中最常用的容器。

    怎么用

    为什么用

    常见陷阱与注意事项

    1. size()返回无符号类型

    2. 迭代器失效

    3. 二维vector初始化陷阱

    4. 访问越界

    5. clear()不释放内存

    6. 比较操作

    7. 高阶技巧:用 emplace_back 代替 push_back

    当 vector 中存储的是 pair 或自定义结构体时,push_back 会先创建一个临时对象,再拷贝/移动进去。而 emplace_back 支持直接在容器末尾原地构造对象,省去了拷贝的开销。


    算法库 algorithm

    是什么

    提供各种算法函数,如排序、查找、反转等,是刷题必备的头文件。

    怎么用

    为什么用

    常见陷阱与注意事项

    1. sort的比较函数必须严格弱序

    2. 二分查找前必须排序

    3. lower_bound和upper_bound的区别

    4. unique只是移动元素,不删除

    5. next_permutation的使用

    6. max_element和min_element返回迭代器

    7. sort的时间复杂度陷阱

    8. 自定义排序的常见错误


    字符串 string

    是什么

    C++标准库的字符串类,比C风格字符串更安全、更易用。

    怎么用

    为什么用

    常见陷阱与注意事项

    1. find返回string::npos表示未找到

    2. substr的参数陷阱

    3. 字符串拼接的效率问题

    4. 字符串比较的字典序

    5. stoi等转换函数的异常

    6. 字符串与字符的区别

    7. 字符串遍历与修改


    数学函数 cmath

    是什么

    C++数学函数库,提供常用数学运算函数。

    怎么用

    为什么用

    常见陷阱与注意事项

    1. pow的精度和效率问题

    2. sqrt的参数必须非负

    3. 浮点数比较的精度问题

    4. 整数除法 vs 浮点除法

    5. abs vs fabs

    6. 三角函数的弧度制

    7. log的底数

    8. 取整函数的区别


    队列 queue

    是什么

    先进先出(FIFO)的数据结构,常用于BFS、任务调度等场景。

    怎么用

    为什么用

    常见陷阱与注意事项

    1. pop()没有返回值

    2. 访问空队列导致未定义行为

    3. priority_queue默认是大顶堆

    4. 自定义优先队列比较

    5. deque的效率问题

    6. 优先队列不支持遍历

    7. 单调队列的实现


    栈 stack

    是什么

    后进先出(LIFO)的数据结构,常用于括号匹配、表达式求值、DFS等场景。

    怎么用

    为什么用

    常见陷阱与注意事项

    1. pop()没有返回值

    2. 访问空栈导致未定义行为

    3. 栈不支持遍历

    4. 括号匹配问题

    5. 单调栈应用

    6. 用栈实现DFS


    集合 set

    是什么

    有序集合,自动去重并排序,基于红黑树实现,时间复杂度O(log n)。

    怎么用

    为什么用

    常见陷阱与注意事项

    1. insert不会覆盖已存在的元素

    2. erase的两种用法

    3. find vs count

    4. lower_bound和upper_bound

    5. 获取最小/最大值

    6. multiset的特殊用法

    7. 自定义比较函数


    映射 map

    是什么

    有序键值对容器,按key自动排序,基于红黑树实现,时间复杂度O(log n)。

    怎么用

    为什么用

    常见陷阱与注意事项

    1. []操作符会自动创建元素

    2. find vs count vs []

    3. 遍历时修改的陷阱

    4. lower_bound和upper_bound

    5. 自定义key类型

    6. 获取第一个和最后一个元素

    7. multimap的特殊用法


    哈希表 unordered_map

    是什么

    无序键值对容器,基于哈希表实现,平均时间复杂度O(1),最坏O(n)。

    怎么用

    为什么用

    常见陷阱与注意事项

    1. []操作符会自动创建元素(同map)

    2. 不支持lower_bound和upper_bound

    3. 自定义key类型需要哈希函数

    4. 哈希冲突导致性能退化

    5. 遍历顺序不确定

    6. 两数之和经典问题

    7. 统计频率


    哈希集合 unordered_set

    是什么

    无序集合,基于哈希表实现,自动去重,平均时间复杂度O(1)。

    怎么用

    为什么用

    常见陷阱与注意事项

    1. 不支持lower_bound和upper_bound

    2. 遍历顺序不确定

    3. 快速去重

    4. 判断是否有重复元素

    5. 自定义元素类型需要哈希函数

    6. 求两个集合的交集、并集、差集


    工具 utility

    是什么

    提供通用工具,最常用的是pair(对组)和swap(交换)。

    怎么用

    为什么用

    常见陷阱与注意事项

    1. pair的比较规则

    2. 自定义pair排序

    3. pair作为map的key

    4. swap的高效性

    5. 使用pair返回多个值

    6. pair的嵌套


    数值算法 numeric

    是什么

    提供数值计算相关的算法,如求和、最大公约数等。

    怎么用

    为什么用

    常见陷阱与注意事项

    1. accumulate的初始值类型很重要

    2. accumulate可以自定义操作

    3. gcd和lcm的注意事项(C++17)

    4. partial_sum的用法

    5. iota生成序列


    C字符串 cstring

    是什么

    C风格字符串处理函数,主要用于char数组操作。

    怎么用

    为什么用

    常见陷阱与注意事项

    1. strlen不包括'\0'

    2. strcpy和strcat不检查边界

    3. strcmp的返回值

    4. memset只能设置0或-1

    5. memset的大小参数

    6. C字符串 vs C++字符串


    常量限制 climits

    是什么

    定义各种数据类型的最大最小值常量。

    怎么用

    为什么用

    常见陷阱与注意事项

    1. 初始化最大最小值

    2. 判断溢出

    3. INT_MIN的特殊性

    4. 无穷大的表示

    5. 浮点数的限制


    位集合 bitset

    是什么

    固定大小的位数组,支持位运算,比bool数组更节省空间。

    怎么用

    为什么用

    常见陷阱与注意事项

    1. 大小必须是编译期常量

    2. 位的顺序(从右到左)

    3. to_ulong和to_ullong的溢出

    4. 位运算的优先级

    5. 状态压缩DP应用

    6. 集合运算

    7. 快速统计1的个数

    8. 常见应用场景


    补充:其他常用头文件

    cctype - 字符处理

    cfloat - 浮点数限制

    cstdlib - 通用工具

    chrono - 时间处理(C++11)

    random - 随机数生成器(C++11)


    总结:头文件选择指南

    按功能分类

    输入输出

    容器

    关联容器

    适配器

    算法

    数学

    其他

    性能对比

    操作vectordequelistsetunordered_set
    随机访问O(1)O(1)O(n)O(log n)-
    头部插入O(n)O(1)O(1)O(log n)O(1)平均
    尾部插入O(1)O(1)O(1)O(log n)O(1)平均
    中间插入O(n)O(n)O(1)O(log n)O(1)平均
    查找O(n)O(n)O(n)O(log n)O(1)平均
    排序支持支持支持自动不支持

    选择建议

    需要动态数组vector 需要频繁头尾操作deque 需要快速查找unordered_set / unordered_map 需要有序set / map 需要栈stack 需要队列queue 需要优先队列priority_queue 需要位运算bitset


    刷题建议

    1. 熟练掌握STL:vector、map、set、queue、stack是基础

    2. 理解时间复杂度:知道什么时候用什么容器

    3. 注意边界条件:空容器、单元素、越界、溢出

    4. 善用algorithm:sort、binary_search、lower_bound等

    5. 避免常见陷阱

      • vector的size()是无符号数

      • map的[]会自动创建元素

      • pop()没有返回值

      • 迭代器失效

      • memset只能设置0或-1

    6. 加速IO:大数据量时使用ios::sync_with_stdio(false)

    7. 使用万能头:竞赛时用#include <bits/stdc++.h>


    ⚠️ 考场终极避坑:Dev-C++ 必须手动开启 C++11

    虽然 Dev-C++ 原生支持 <bits/stdc++.h> 万能头,但国内大部分考场(如机试、CSP、蓝桥杯等)提供的往往是古董级的 Dev-C++ 5.11 版本

    这个版本默认采用的是 C++98 标准。如果不做任何设置,你在平时刷题时习以为常的现代语法都会直接引发编译报错(Compile Error),例如:

    ✅ 坐下后的第一件事:开启 C++11 支持

    为了在考场上能正常使用现代 C++ 的便利特性,请在敲第一行代码前,严格按照以下步骤配置你的 Dev-C++:

    1. 在顶部菜单栏点击 工具 (Tools) -> 编译选项 (Compiler Options)

    2. 在弹出的窗口中,勾选 编译时加入以下命令 (Add the following commands when calling the compiler)

    3. 在下方的输入框中,准确地填入以下命令(注意全是小写,没有空格):

    -std=c++11

    1. 点击 确定

    配置完成后,配合万能头文件,你的 Dev-C++ 才是真正意义上的考场“完全体”。

     

    🛡️ 极端环境预案:考场不支持 C++11 怎么办?

    如果由于客观限制无法开启 C++11,编译器会退化到 C++98 标准。为了防止在考场上因为语法报错而心态崩溃,请务必牢记以下 5 个“语法退化”替换方案:

    1. 嵌套模板的“空格”噩梦(最容易踩的坑)

    在 C++98 中,连续的两个右尖括号 >> 会被编译器直接解析为“右移位运算符”,从而引发莫名其妙的语法错误。

    2. 哈希容器失效

    C++98 的标准库中没有哈希表(即 unordered_ 系列)。

    3. 禁用 auto 和 范围 for 循环

    现代 C++ 极其方便的类型推导和遍历方式在 C++98 中完全不存在。

    4. 告别大括号 {} 列表初始化

    不能再直接给容器赋初值了。

    5. 字符串转换函数 to_string()stoi() 失效