Ale*_*Dan 3 c++ stream buffered unbuffered
在缓冲流的情况下,它在一本书中说它等到缓冲区已满,然后写回监视器.例如:
cout << "hi";
Run Code Online (Sandbox Code Playgroud)
"缓冲区已满"是什么意思.
cerr << "hi";
Run Code Online (Sandbox Code Playgroud)在我的书中说,发送到的所有内容都会cerr立即写入标准错误设备,这是什么意思?
char *ch;
cin>> ch; // I typed "hello world";
Run Code Online (Sandbox Code Playgroud)在这个例子ch中将被分配为"hello"并且"world"将被忽略是否意味着它仍然在缓冲区并且它将影响未来语句的结果?
Jam*_*nze 12
你的书似乎没什么帮助.
1)输出流将其字节发送到a std::streambuf,其中可能包含缓冲区; 使用的std::filebuf(派生自streambuf)和std::ofstream通常会被缓冲.这意味着当你输出一个字符时,它不一定立即输出; 它将被写入缓冲区,并仅在缓冲区已满时输出到OS,或者以某种方式显式请求它,通常是通过调用
flush()流(直接或间接地,通过使用std::endl).然而,这可能会有所不同; 输出std::cout与其同步
stdout,并且大多数实现将或多或少遵循stdoutfor 的规则,
std::cout如果输出转到交互式设备,则更改缓冲策略.
无论如何,如果你不确定,并且你想确保输出确实离开你的程序,只需添加一个flush的调用.
2)你的书在这里错了.
缓冲策略之一是unitbuf; 这是std::ostream您可以设置或重置的标志
(std::ios_base::set()和
std::ios_base::unset()- std::ios_base是基类
std::ostream,因此您可以在std::ostream
对象上调用这些函数).当unitbuf设置,std::ostream增加了一个电话flush()
给每个输出功能的结束,所以当你写:
std::cerr << "hello, world";
Run Code Online (Sandbox Code Playgroud)
在输出字符串中的所有字符后,将刷新流,前提unitbuf是已设置.在启动时,unitbuf设置为std::cerr; 默认情况下,它不会在任何其他文件上设置.但您可以随意设置或取消设置.我建议不要将其取消std::cerr,但如果std::cout输出到交互式设备,那么将它设置在那里是很有意义的.
请注意,这里所讨论的只是缓冲区streambuf.通常,OS也会缓冲.所有刷新缓冲区都是将字符传输到操作系统; 这一事实意味着您无法ofstream在需要事务完整性时直接使用
.
3)当您使用输入字符串或字符缓冲区时>>,第
std::istream一个跳过前导空白区域,然后输入最多但不包括下一个空白区域.在标准的正式术语中,它从流中"提取"字符,以便不再看到它们(除非您寻求,如果流支持它).下一个输入将从前一个左侧关闭的位置拾取.以下字符是在缓冲区中还是在磁盘上,实际上是无关紧要的.
请注意,输入的缓冲有些复杂,因为它发生在几个不同的级别,而在OS级别,它根据设备采用不同的形式.通常,OS将按扇区缓冲文件,通常预先读取几个扇区.除非遇到文件末尾,否则操作系统将始终返回所需数量的字符.大多数操作系统将逐行缓冲键盘:从读取请求返回直到输入完整的行,并且永远不会在读取请求中返回超出当前行末尾的字符.
以与std::ostream使用streambuf输出相同的方式,
std::istream使用一个来获取每个单独的字符.在这种情况下std::cin,它通常是一个filebuf; 当istream
请求一个字符时,filebuf如果有一个字符,它将从缓冲区返回一个字符; 如果没有,它将尝试重新填充缓冲区,从OS请求例如512(或其缓冲区大小)字符.如上所述,其将根据其对设备的缓冲策略进行响应.
无论如何,如果std::cin已连接到键盘并且您已键入"hello world",则最终将由流读取您键入的所有字符.(但是如果你正在使用>>,那么你将看不到很多空白.)