以前总是听说C++的cin
、cout
效率低下,导致我在做算法题的时候总是使用C风格的scanf
、printf
,敲起来真是麻烦得多2333
后来经过学习才发现,其实C++为了兼容C,而在i/o上做了一些文章,cin
、cout
经过手动配置,也能够胜任在算法中的工作
std::cin做了额外的工作
cin
之所以显得慢,是因为出于安全考虑,做了以下两个工作:
- 与
std::cout
绑定。每次std::cin
从缓冲区读入内容之前,会执行std::cout.flush()
刷新缓冲。 - 与
stdio
同步。确保混用 C 风格的 I/O 操作如(scanf
,printf
)不会引发问题。
而如果在编码时能够人为地避免这些问题,就可以省去这些工作,从而达到加速cin
的目的。
std::cin.tie
cin.tie
是将cin
和某个ostream
绑定的函数,空参数的话返回当前的输出流指针。
根据 cplusplus网站 的描述,根据传递的参数不同,该函数具有两种功能:
- (1)无参调用: ostream* tie() const;
- (2)含参调用: ostream* tie (ostream* tiestr);
The first form (1) returns a pointer to the tied output stream.
形式(1)返回当前绑定的输出流指针
The second form (2) ties the object to tiestr and returns a pointer to the stream tied before the call, if any.
形式(2)将cin和tiestr绑定,并返回在这之前绑定的流指针(如果有的话)
The tied stream is an output stream object which is flushed before each i/o operation in this stream object.
绑定的流是一个输出流对象,该对象在每次 i/o 操作之前都会进行刷新。
cplusplus网站还有一个代码示例,为方便理解,在这里贴出我添加了注释的版本:
// redefine tied object
#include <iostream> // std::ostream, std::cout, std::cin
#include <fstream> // std::ofstream
int main() {
std::ostream* prevstr;
std::ofstream ofs;
// ofs 绑定文件 test.txt
ofs.open("test.txt");
// 控制台输出
std::cout << "tie example:\n";
// cin.tie 返回 std::cout 的指针,字符串输出到控制台
*std::cin.tie() << "This is inserted into cout";
// 将文件输出流 ofs 绑定在 std::cin 上
// 同时返回原先绑定在cin上的输出流指针(指向控制台输出)
prevstr = std::cin.tie(&ofs);
// cin.tie 返回 ofs 的指针,字符串输出到文件 test.txt
*std::cin.tie() << "This is inserted into the file";
// 恢复为控制台输出
std::cin.tie(prevstr);
// 关闭文件
ofs.close();
return 0;
}
利用形式(2),在默认状态下,我们可以通过给该函数传递空指针,从而解除cin
与cout
的绑定,省去了第一项额外工作的时间,具体代码如下:
std::cin.tie(nullptr);
//或者std::cin.tie(0);
ios::sync_with_stdio
调用该函数可以切换C++流和C流的同步状态
它的原型是:
static bool sync_with_stdio( bool sync = true )
这个同步是默认打开的,所以在默认情况下 C++ 流上做的操作会被同步到相应的 C 流中,这就为混和使用C++流和C流提供了可能。
倘若我们不混和使用C++流和C流(就比如在做算法题的时候),我们可以通过向该函数传递false
参数值,以解除 C++ 流与 C 流的同步:
std::ios::sync_with_stdio(false);
这样一来第二项额外工作也免了。
所以,通过调用这两个函数,我们可以放心地将算法的I/O交给cin
和cout
处理,不用担心因为它们而TLE了
#include <iostream>
int main(){
std::cin.tie(nullptr);
std::ios::sync_with_stdio(false);
// 然后写你的代码去吧...
}