默认cin因同步c标准流、频繁函数调用与状态检查,处理千万级整数时开销巨大,实测比fread慢5–10倍;必须用ios::sync_with_stdio(false)和cin.tie(nullptr)优化,或直接fread手动缓冲读取。

为什么 cin 读千万级整数会慢到卡死
默认 cin 是同步 C 标准流的,每次调用都要检查 stdin 缓冲区、做格式解析、类型安全检查,还带异常抛出逻辑。对千万级 int(比如 1e7 个),这相当于执行千万次函数调用+锁+状态判断,实测比 fread 慢 5–10 倍。
关键不是“能不能关”,而是必须关——否则根本达不到 I/O 瓶颈,CPU 都在等 cin 自身的开销。
-
ios::sync_with_stdio(false)关闭同步(必须在任何输入前调用) -
cin.tie(nullptr)解绑cin和cout(避免每次cin后自动 flushcout) - 别混用
scanf/cin:一旦调用了scanf,sync_with_stdio(false)就失效
用 fread 手动缓冲读入整数数组最快
绕过所有流封装,直接从 stdin 文件描述符批量读字节,再按需解析。适用于纯数字、空格/换行分隔的场景(如 OJ 输入)。
核心思路:一次 fread 读几千字节进缓冲区,用指针逐字符解析数字,跳过空白,转成 int 存数组。
- 缓冲区大小建议设为
1 (64KB),太小频繁系统调用,太大无益 - 解析时用
ch - '0'比atoi快得多;注意负号和多位数 - 不要用
std::string或std::vector::push_back在循环里动态扩容——预分配好数组
示例片段:
static char buf[1 = '0' && *p <h3> <code>getchar_unlocked</code> 适合单线程、Linux 环境下的极致优化</h3><p>这是 GNU libc 提供的非线程安全版 <code>getchar</code>,省去了锁开销,在单进程读标准输入时比 <code>fread</code> 缓冲解析还快约 10–15%。</p><p>但注意:<code>getchar_unlocked</code> 不是 C++ 标准函数,Windows 下不可用,且多线程环境下会崩溃。</p>
- 只在明确单线程、Linux、追求极限性能时启用(如 ACM 现场赛)
- 仍需手动跳过空白、处理负号、防溢出(尤其
int边界) - 别和
cin/scanf混用——它们内部也用getchar,会破坏状态
别忽略输入格式细节导致解析失败
快的前提是格式可控。如果输入含多余空格、空行、末尾换行、或数字间有制表符,手写解析器很容易崩或漏读。
- 用
isspace(*p)判断空白更稳妥,而不是只判' '和'\n' - 千万级数据下,少读一个数可能让后续全部错位,务必加计数校验(如读完后检查
i == expected_n) - 如果输入含十六进制、科学计数法、浮点数,
fread解析成本陡增,此时应退回到scanf或std::cin(并接受速度损失)
真正难的不是写出最快的读入,而是让快的代码在各种边界输入下稳定不出错——尤其是线上环境无法调试时。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











