在实现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.