Dotcpp  >  编程教程  >  经验与技巧  >  C++输入输出的效率优化

C++输入输出的效率优化

点击打开在线编译器,边学边练

看到不少初学编程的同学是学的C++,或者学了C再学C++之后,会习惯性的用C风格的C++代码编写程序,因此习惯了cout、cin输入输出,但在默认情况下,同样输入输出语句,C语言的scanf和printf ,比C++的std::cin和std::cout 要快的多。这一点大家在实际做题过程中或许有所感受,比如有些题同样的代码,用cout cin就会超时,而用pritnf scanf就可以通过。

cin、cout 与 scanf、printf 的实际速度差会随编译器和操作系统的不同发生一定的改变。如果想要进行详细对比,请以实际测试结果为准。


如何优化输入输出?

1.取消缓冲区同步语句  std::ios::sync_with_stdio(false)

C++中cin,cout效率比较低,是因为先把要输出的东西存入缓冲区与C语言中的stdio同步后,再输出,导致效率降低,而这个语句的作用是取消缓冲区同步,直接使用,由此可节省时间,使效率与scanf与printf相差无几。

但需要注意的一点是,因为取消与stdio的同步之后,就不建议再使用 printf 与 scanf了,否则实际输出效率可能还会与预期不符。只能用cin 与 cout,以使得cout和cin的效率得到提高


2.使用tie函数减少IO负担

首先我们需要了解一个可能不知道的事实,那就是C++中的cout和cin并不是独立的,即在使用cout的时候,cin也会执行,反之亦然。正是由于这种情况,当我们遇到数据集超大造成 cin 超时(TLE)的时候,我们可能会认为这是cin的效率不及scanf的原因。其实是输入缓冲区,flush缓冲区,占用了时间。

tie 是将两个 stream 绑定的函数,空参数的话返回当前的输出流指针。如代码:

 std::cin.tie(0)

在默认的情况下 std::cin 绑定的是 std::cout,每次执行 << 操作符的时候都要调用 flush() 来清理缓冲区(stream buffer),这样会增加 IO 负担。可以通过这句代码std::cin.tie(0)来解除 std::cin 与 std::cout 的绑定,进一步加快执行效率。一个完整且简单的例子如下:

using namespace std;
int main()
{
    int i;
    cin.tie(&cout);
    cout<<"Enter a number.";
    cin>>i;
}

用户输入5然后敲回车后

代码执行的过程是,直接将“Enter a number."输出到控制台上,然后直接将用户输入的5读入到i中,中间不经过缓冲区。

因此当我们要大量读取数据的时候可以tie函数解绑,来加快数据读取。


但需要注意的是,在解除了 std::cin 和 std::cout 的绑定后,程序中必须手动 flush 才能确保每次 std::cout 展现的内容可以在 std::cin 前出现。这是因为 std::cout 被 buffer 为默认设置。例如:

std::cout<< "Please input your name: "<<std::flush;  
// 或者std::endl;  因为每次调用std::endl都会flush输出缓冲区,而 \n 则不会。
// 但请谨慎使用,过多的flush也会影响程序效率
std::cin >> name;



本文固定URL:https://www.dotcpp.com/course/836

C语言网提供由在职研发工程师或ACM蓝桥杯竞赛优秀选手录制的视频教程,并配有习题和答疑,点击了解:

一点编程也不会写的:零基础C语言学练课程

解决困扰你多年的C语言疑难杂症特性的C语言进阶课程

从零到写出一个爬虫的Python编程课程

只会语法写不出代码?手把手带你写100个编程真题的编程百练课程

信息学奥赛或C++选手的 必学C++课程

蓝桥杯ACM、信息学奥赛的必学课程:算法竞赛课入门课程

手把手讲解近五年真题的蓝桥杯辅导课程

Dotcpp在线编译      (登录可减少运行等待时间)