在实现C++中非阻塞式的用户输入中发现,在没有设置in.sync_with_stdio(false)
时,in.rdbuf()
里面总是空的。
// in.sync_with_stdio(false);
std::cout << in.rdbuf().in_avail() << std::endl; // always 0;
这个可能是因为如果std::cin
与stdio
同步,std::cin
就没有自己的缓冲区,而是与stdin
共用缓冲区。通过设置in.sync_with_stdio(false)
之后,std::cin
就有了自己的缓冲区,从而能通过缓冲区内容大小,判断用户是否在输入。
不过解绑之后, C++和 C 的输入输出使用不同的缓冲区,会导致输入和输出顺序无法保障。因此要么总是用std::cin/std::cout
,要么总是用printf/scanf
,尽量不要混用。
注:该机制可能依赖编译器和操作系统的实现。
在刷 ACM OJ 或者 leetcode 时,很多人都会在最开头添加下面代码:
static int __ = []() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
return 0;
} ();
这个道理是类似的。通过解绑std::ios
和printf/scanf
的缓冲区,提升性能。cin.tie(nullptr)
则是当输入输出切换时,不会刷新缓冲区,从而更进一步提升性能 —— 默认std::cin
是与std::cout
绑定的,所以每次操作的时候(也就是调用<<
或者>>
)都要调用flush
刷新。
Q. E. D.