参考资料
前言
最近在刷算法题的时候,经常看到大佬们的代码里都会加这么几行:
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
一开始我也不太明白这是干什么的,只是机械地复制粘贴。后来遇到一道题,数据量特别大,不加这几行就TLE(超时),加了就AC了。这才意识到这几行代码的重要性,于是专门学习了一下。
今天就来详细讲讲这三行”魔法代码”到底是什么,为什么能加速,以及使用时要注意什么。
为什么需要加速?
在C++中,有两套输入输出系统:
| 类型 | 函数 | 特点 | 
|---|---|---|
| C风格 | scanf, printf | 
速度快 ⚡ | 
| C++风格 | cin, cout | 
速度慢 🐌 | 
为什么cin/cout会慢?
默认情况下,cin/cout为了兼容C语言的scanf/printf,做了很多额外的同步工作。这导致在处理大量数据时,cin/cout可能比scanf/printf慢2-3倍!
举个例子:
假设要读入100万个整数:
- 用
scanf:可能只需要0.3秒 - 用
cin(不加速):可能需要1秒 - 用
cin(加速后):也能达到0.3秒左右 
在算法竞赛中,0.7秒的差距可能就是AC和TLE的区别!
三行代码详解
第一行:ios::sync_with_stdio(0)
作用:取消C/C++流的同步
默认情况(sync = true):
C++的cin/cout和C的scanf/printf是同步的,这意味着:
- ✅ 可以随意混用两种输入输出方式
 - ❌ 但cin/cout要保持与scanf/printf的同步,会变慢
 
设置为false后:
ios::sync_with_stdio(false);
// 或者简写为
ios::sync_with_stdio(0);
- ✅ cin/cout速度大幅提升,接近scanf/printf
 - ❌ 不能再混用cin/cout和scanf/printf
 
代码示例
// ❌ 错误用法:混用导致问题
ios::sync_with_stdio(false);
cin >> x;           // C++风格
scanf("%d", &y);    // C风格 - 不能这样!
printf("%d", z);    // C风格 - 不能这样!
// ✅ 正确用法:统一用C++风格
ios::sync_with_stdio(false);
cin >> x;
cin >> y;
cout << x << " " << y << "\n";
形象比喻
想象有两条传送带:
同步模式(默认):
C传送带   ─┐
           ├─→ 合并成一条,能混用但慢
C++传送带 ─┘
不同步模式(加速):
C传送带   ──→ 各走各的,快但不能混用
C++传送带 ──→
第二行:cin.tie(0)
作用:解除cin与cout的绑定
默认情况(绑定):
cin和cout是绑定在一起的。每次使用cin输入之前,会自动刷新cout的缓冲区。
这是为了保证交互式程序的正确性:
cout << "请输入你的年龄:";
cin >> age;  // 输入前会先把"请输入你的年龄:"显示出来
解除绑定后:
cin.tie(nullptr);
// 或者简写为
cin.tie(0);
- ✅ 不再自动刷新cout,速度更快
 - ⚠️ 对于大多数算法题没有影响
 - ⚠️ 交互题可能需要手动刷新
 
什么时候需要手动刷新?
对于交互题(需要实时输入输出的题目),可能需要:
cout << answer << endl;  // endl会自动刷新
// 或者
cout << answer << "\n";
cout.flush();  // 手动刷新
速度提升原理
// 默认情况(绑定)
for (int i = 0; i < 1000000; ++i) {
    cout << i << " ";  // 输出
    cin >> x;          // 输入前自动刷新cout(慢!)
}
// 解除绑定后
cin.tie(nullptr);
for (int i = 0; i < 1000000; ++i) {
    cout << i << " ";  // 输出
    cin >> x;          // 不会自动刷新(快!)
}
第三行:cout.tie(0)
作用:解除cout的绑定
真相:这行基本没用!
cout默认就没有绑定任何流,所以这行代码:
cout.tie(nullptr);
写不写都一样,不会有任何性能提升。
为什么很多人还写?
主要有两个原因:
- 习惯性:复制模板时一起复制了
 - 求心理安慰:反正写了也没坏处
 
建议
可以不写! 但写了也不会出错,看个人习惯。
完整使用模板
标准竞赛模板
#include <bits/stdc++.h>
using namespace std;
int main() {
    // 输入输出加速
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    // cout.tie(nullptr);  // 这行可以省略
    
    // 你的代码
    int n;
    cin >> n;
    cout << n << "\n";  // 用 \n 代替 endl(更快)
    
    return 0;
}
简化写法(逗号表达式)
int main() {
    ios::sync_with_stdio(0), cin.tie(0);
    
    // 你的代码
    
    return 0;
}
这种写法利用了C++的逗号表达式,三个语句会依次执行,效果完全相同。
性能对比测试
我自己测试了一下,读入100万个整数的耗时:
| 方法 | 耗时 | 相对速度 | 
|---|---|---|
scanf/printf | 
0.28秒 | 基准(最快)⚡⚡⚡ | 
cin/cout(不加速) | 
0.89秒 | 慢3倍 🐌 | 
cin/cout(加速) | 
0.31秒 | 接近scanf ⚡⚡⚡ | 
可以看到,加速后的cin/cout已经非常接近scanf/printf了!
注意事项与常见错误
⚠️ 注意1:不能混用C/C++输入输出
ios::sync_with_stdio(false);
// ✅ 可以这样
cin >> x;
cout << x;
// ❌ 不能这样
cin >> x;
printf("%d", x);  // 错误!输出可能乱序
// ❌ 也不能这样
scanf("%d", &x);  // 错误!
cout << x;
// ❌ getchar也不行
getchar();  // 错误!getchar是C函数
记住:加了加速后,只能用cin/cout,不能用任何C风格的输入输出函数!
⚠️ 注意2:用\n代替endl
// 推荐写法(快)
cout << x << "\n";
// 不推荐写法(慢)
cout << x << endl;
原因: endl会强制刷新缓冲区,而\n不会。在循环中大量使用endl会严重影响性能。
⚠️ 注意3:数据量小时可以不加
- 数据量 < 10,000:加不加都行,差别不大
 - 数据量 > 100,000:建议加上
 - 数据量 > 1,000,000:必须加,否则可能TLE
 
⚠️ 注意4:交互题要小心
对于需要实时交互的题目(比如猜数字游戏),可能需要手动刷新:
ios::sync_with_stdio(false);
cin.tie(nullptr);
// 输出后需要立即显示
cout << "我猜50\n";
cout.flush();  // 手动刷新
cin >> response;
或者对于交互题,干脆不加速:
// 交互题可以不加这两行
// ios::sync_with_stdio(false);
// cin.tie(nullptr);
cout << "我猜50" << endl;  // endl会自动刷新
cin >> response;
实战案例
案例1:大量数据读入
#include <bits/stdc++.h>
using namespace std;
int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    
    int n;
    cin >> n;
    
    vector<int> a(n);
    for (int i = 0; i < n; ++i) {
        cin >> a[i];  // 快速读入
    }
    
    for (int i = 0; i < n; ++i) {
        cout << a[i] << "\n";  // 快速输出
    }
    
    return 0;
}
案例2:多组测试数据
#include <bits/stdc++.h>
using namespace std;
int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    
    int T;
    cin >> T;
    while (T--) {
        int n, k;
        cin >> n >> k;
        // 处理数据...
        cout << result << "\n";
    }
    
    return 0;
}
总结
三行代码的作用总结
| 代码 | 作用 | 重要性 | 副作用 | 
|---|---|---|---|
ios::sync_with_stdio(false) | 
取消C/C++流同步 | ⭐⭐⭐ 很重要 | 不能混用scanf/printf | 
cin.tie(nullptr) | 
解除cin与cout绑定 | ⭐⭐ 有用 | 交互题需要注意 | 
cout.tie(nullptr) | 
解除cout绑定 | ⭐ 基本没用 | 无 | 
记忆口诀
sync 同步关,cin cout 更快跑
tie 绑定解,输入输出不等待
cout.tie 没啥用,写不写都无所谓
什么时候使用?
- ✅ 算法竞赛:基本上都要加
 - ✅ 大数据量题目(n > 100,000):必须加
 - ⚠️ 交互题:谨慎使用,可能需要手动刷新
 - ❌ 小数据量题目(n < 10,000):可以不加
 
最佳实践
#include <bits/stdc++.h>
using namespace std;
int main() {
    // 标准竞赛模板
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    
    // 记住:
    // 1. 只用 cin/cout,不用 scanf/printf
    // 2. 用 \n 代替 endl
    // 3. 不要混用 C/C++ 输入输出
    
    // 你的代码...
    
    return 0;
}