【C++】ios::sync_with_stdio(false) 与 cin.tie(nullptr) 加速 IO
目录&索引一、前言题目二、ios::sync_with_stdio(false)三、cin.tie(nullptr)四、小结一、前言前面遇到大数据量(cin、cout 数据量级达到 1e5、1e6 ),考虑因为 IO 性能报错 TLE 选择 scanf、printf 替代 cin、cout,故解决问题,却没有深入研究其中的原因。只知关键词——同步,虽本质相同但差之千里,故记录本文。针对上述
一、前言
之前写题遇到大数据量(cin、cout 数据量级达到 1e5、1e6 ),因为考虑 IO 性能报错 TLE,故选择 scanf、printf 替代 cin、cout,以解决问题。一直以来没有深入研究其中原因,只知关键词——同步,虽是本质但差之千里,今究其因,记录本文。
针对上述场景无法 AC,起因是打 LC 周赛发现 top 选手用的下述代码:
// 已做相关改进,包括 cin.tie(0) 被替换为 cin.tie(nullptr),删掉不必要的 cout.tie(0),因不涉及本文主题故不详细展开
using namespace std;
ios::sync_with_stdio(false);
cin.tie(nullptr);
题目
二、ios::sync_with_stdio(false)
在调用 ios::sync_with_stdio(false) 后,cout 与 stdout 不再共享同一块缓冲区,它们分别管理自己的缓冲区。简述,函数作用为设置标准 C++ 流是否与标准 C 流在每次输入/输出操作后同步(官方文档,见下图)。
正是因为这种同步,所以 cin、cout 比 scanf、printf 速度要慢,如果我们在使用 cin、cout 输入输出前加一句 ios::sync_with_stdio(false),即取消缓冲区同步,可节省时间,效率与 scanf、printf 相差无几。
具体功能,需要注意以下几点:
1、实践中,这表示同步的 C++ 流为无缓冲,而每次 C++ 流上的 I/O 都立即应用到对应 C 流的缓冲区。这使得能自由地混合 C++ 与 C I/O 。
2、同步的 C++ 流保证为线程安全(从多个线程输出的单独字符可能交错,但无数据竞争)。
3、若关闭同步,则允许 C++ 标准流独立地缓冲其 I/O ,可认为这在某些情况下更快。
4、所有八个标准 C++ 流默认与其相应的 C 流同步。
5、若在标准流上已出现 I/O 后调用此函数,则行为是实现定义的:有的实现无效果,有的实现销毁读取缓冲区。
三、cin.tie(nullptr)
tie 是一个函数,将两个 stream 绑定,空指针的话返回当前输出流指针(官方文档,见下图)。
函数介绍(注意返回值):
std::basic_ostream<CharT,Traits>* tie() const; // 返回当前联系流。若无联系流,则返回空指针。
std::basic_ostream<CharT,Traits>* tie( std::basic_ostream<CharT,Traits>* str ); //设置当前联系流为 str ,返回操作前的联系流。
若无联系流,则返回空指针。
cin 默认是与 cout 绑定,所以每次 cin 操作的时候都在联系流(即输出流)调用 flush(),这样增加了 IO 负担,通过 cin.tie(nullptr) 来解除 cin 和 cout 之间的绑定,进一步加快执行效率。同时,解除绑定带来的效果,详述如下:
cin 默认绑定了 cout 来同步在控制台输出。“绑定”的效果,每当被“绑定”的对象有出入或输出操作,就会即时刷新(本质,在一定刷新频率下刷新)“绑定”的对象的缓冲区,以达到即时回显的效果。cout 没有默认绑定其他输出,所以 cout.tie() 获取到空指针。
代码验证:
#include <iostream>
using namespace std;
int main() {
cout << "cin.tie(): " << cin.tie() << endl;
cout << "cin.tie(nullptr): " << cin.tie(nullptr) << endl; // 返回操作前的联系流
cout << "cin.tie(): " << cin.tie() << endl;
cout << endl;
cout << "cerr.tie(): " << cerr.tie() << endl;
cout << "cerr.tie(nullptr): " << cerr.tie(nullptr) << endl; // 返回操作前的联系流
cout << "cin.tie(): " << cin.tie() << endl;
cout << endl;
cout << "clog.tie(): " << clog.tie() << endl;
cout << "cout.tie(): " << cout.tie() << endl;
return 0;
}
输出:
cin.tie(): 0x55dea3046140
cin.tie(nullptr): 0x55dea3046140
cin.tie(): 0
cerr.tie(): 0x55dea3046140
cerr.tie(nullptr): 0x55dea3046140
cin.tie(): 0
clog.tie(): 0
cout.tie(): 0
四、小结
对文章内容有不解,请随时留言。
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)