C/C++缓冲区刷新问题
Buffers are normally maintained by the operating system, which determines the optimal time to write the data automatically to disk: when a buffer is full, when a stream is closed, or when a program terminates normally without closing the stream.
当我们对文件流进行操作的时候,它们与一个streambuf 类型的缓存(buffer)联系在一起。这个缓存(buffer)实际是一块内存空间,作为流(stream)和物理文件的媒介。例如,对于一个输出流, 每次成员函数put (写一个单个字符)被调用,这个字符不是直接被写入该输出流所对应的物理文件中的,而是首先被插入到该流的缓存(buffer)中。
当缓存被排放出来(flush)时,它里面的所有数据或者被写入物理媒质中(如果是一个输出流的话),或者简单的被抹掉(如果是一个输入流的话)。这个过程称为同步(synchronization),它会在以下任一情况下发生:
1.进程/线程/程序正常结束时,将刷新所有的输出缓冲区。
2.缓冲区满了,在这种情况下,缓冲区将会在写下一个值之前刷新。
3.用操纵符显示地刷新缓冲区,如用endl。
4.在每次输出操作执行完毕后,用unitbuf操纵符设置流的内部状态,从而清空缓冲区。
5.默认情况下cin与cout是关联的,在cin时将刷新输出缓冲区。
====================================
fflush Defined in header <stdio.h>
int fflush( FILE *stream );
For output streams (and for update streams on which the last operation was output), writes any unwritten data from the stream's buffer to the associated output device.
If stream is a null pointer, all open output streams are flushed, including the ones manipulated within library packages or otherwise not directly accessible to the program.
eg.
fflush(stdout);
====================================
std::flush Defined in header <ostream>
template< class CharT, class Traits >
std::basic_ostream<CharT, Traits>& flush( std::basic_ostream<CharT, Traits>& os );
An explicit flush of std::cout is also necessary before a call to std::system, if the spawned process performs any screen I/O (a common example is std::system("pause") on Windows). In most other usual interactive I/O scenarios, std::endl is redundant when used with std::cout because any input from std::cin, output to std::cerr, or program termination forces a call to std::cout.flush().
When a complete line of output needs to be flushed, the std::endl manipulator may be used.
When every output operation needs to be flushed, the std::unitbuf manipulator may be used.
eg.
std::cout.flush();
====================================
std::ios_base::sync_with_stdio
std::ios_base::sync_with_stdio(true); //默认情况同步,cout与stdout共享同一缓冲区。
std::ios_base::sync_with_stdio(false); //取消同步,cout与printf不再共享同一缓冲区,混用cout与printf会乱序。
正是这种同步,导致cin/cout比scanf/printf速度慢。
https://www.byvoid.com/blog/fast-readfile
====================================
std::basic_ios::tie
A tied stream is an output stream which is synchronized with the sequence controlled by the stream buffer (rdbuf()), that is, flush() is called on the tied stream before any input/output operation on *this.
默认情况下,cin与cout是绑定的,cin会刷新cout的缓冲区。理论上该情况下,cin与cout可共享一个缓冲区,但似乎没有这么实现的。
std::cin.tie(0); //tie在绑定了cout后,会保证在cin执行前刷新cout的缓冲区。cin.tie(0)解除了绑定,则并不保证cout在cin之前刷新,但也不保证不会刷新。
https://stackoverflow.com/questions/14052627/why-do-we-need-to-tie-stdcin-and-stdcout