- 如果C++代模块中没有使用C的输入或输出函数,而是只用到了C++的输入输出函数,则可以使用
std::ios::sync_with_stdio(false)
来关闭同步。这个函数是一个“是否兼容stdio”的开关,C++为了兼容C,保证程序在使用了std::printf和std::cout的时候不发生混乱,将输出流绑到了一起。解绑后,速度会有质的提升。实际上,如果未关闭同步,C++的流本身并没有缓冲,每个C++流的操作都是直接与C的流缓冲进行交互。这种情况下,C++的流操作和C的流操作就可以混用,而不会发生问题。此外,未关闭同步的C++流也是线程安全的,多个线程的单个字符输出可能会发生交错,但不会发生数据竞争。如果关闭了同步,则每个C++流操作都有自己的缓冲区,这在某些情况下会极大地加速流操作,但是就不是线程安全的了,且此时不能与C的IO函数混用。 - 此外,
std::cin
与std::cout
也有绑定,导致每次std::cout
执行后并在执行std::cin
时都会刷新输出缓冲区,也就是说每次使用std::cin
进行数据输入时,都会调用一次std::cout.flush()
函数,对缓冲区进行刷新。解除同步能够进一步加快IO速度:std::cin.tie()
。如果不传入形参,则函数只会返回与std::cin
进行同步绑定的std::ostream
对象的指针。如果形参传入一个std::ostream
类型的指针,则表示将std::cin
与此对象进行同步绑定,并返回前一个与std::cin
进行绑定的std::ostream
类型的指针。如果形参传入nullptr
,那就表示解绑的意思啦。注意,tie()
函数不止用于std::cin
对象,对于任何C++的std::istream
对象(如std::ifstream
对象)都有对应的tie()
成员函数,都能加快读写速度; - 使用
tie()
解除绑定后,一定要注意在使用std::ostream
输出数据后并在使用std::istream
输入数据前要主动flush
缓冲区的内容,不然容易出错; - 注意,执行
std::ios::sync_with_stdio(false)
后,stdio
中的printf
与scanf
之间的同步也会被取消,不过多多测试; - 注意,使用了上述两个优化后,就不能混合使用
scanf
,getchar
,gets
,fgets
,fscanf
了。注意,混合使用是指对同一个文件混合使用,对不同文件访问是没问题的; - 由上可知,
std::ios::sync_with_stdio(false)
关闭了与C流的同步,启用了C++自己的缓冲区,能够加快输出操作,而tie(nullptr)
是解绑C++的输入输出流,从而使得执行输入的时候,不会主动刷新缓冲区,能够加快输入操作; - 有人测试得出,使用
fread()
和fwrite()
速度可能会更快,可以看下面的链接。
详细测试不同IO函数的速度
探寻C++最快的读取文件的方案
std::ios::sync_with_stdio