std :: cout是缓冲的吗?

时间:2014-11-17 15:19:51

标签: c++ cout

阅读“Scott Meyers”中一篇陈旧但有趣的文章

http://aristeia.com/Papers/C++ReportColumns/novdec95.pdf

基本上它更倾向于使用'\n'而不是std::endl(我同意并且多年来一直使用相同的补充)。

但是最后一部分表明这不包括在他的书中,因为整个事情由于两点而变得没有意义:

  1. std::cout没有缓冲。
  2. 未明确定义std :: cout上的ios::unitbuf状态(因此取决于实现)。
  3. 我快速查看但未找到1的明确标准参考是真的。 std::cout是否与我一直理解的相反无缓冲?

5 个答案:

答案 0 :(得分:17)

是的,它被缓冲了:

  

C ++ 11 27.4.2 [narrow.stream.objects] / 3   :对象cout控制输出到与对象stdout

关联的流缓冲区

本文引用了1995年草案版本的C ++ 98标准。我不知道这是否可能有所不同。

对于第2点,unitbuf最初在所有流上都为false(由basic_ios构造函数的后置条件指定),cerrwcerr除外另有明确说明。同样,在提到的古代草案中,这可能会有所不同。

答案 1 :(得分:10)

首先,不要求std::cout(甚至std::cerr) 无缓冲。唯一的要求是std::cerr std::basic_ios::unitbuf设置(以便在每个结尾处刷新 输出函数:<<或非格式化输出函数)。在另一 除非你打电话给std::basic_ios::sync_with_stdio(false), 输出到C ++流并输出到相应的 C流(即std::coutstdout)必须具有相同的效果。 从理论上讲,这可以通过几种方式完成:stdout函数可以 转发到std::cout的那些,std::cout输出可以转发到 stdout,或者他们可以共享一些常见的缓冲区实现 引擎盖。在实践中,几乎所有实现都有std::cout 转发到stdout

C指定stderr未完全缓冲,stdout可能 只有在可以确定不参考的情况下才能完全缓冲 交互设备(用于某些实现定义的含义) “互动设备”)。通常,stdout将进行行缓冲(a 在iostream中不存在的概念),stderr将是 没有缓冲,但C标准不保证(可能不是 今天真实 - 我最后一次真正看上去是二十多年了 前)。无论如何,只是转发到stdout的实现将会 遵循它转发到的C实现的规则,并且遵循它的规则 并不需要采取一些措施来确保输出 std::coutstdout以正确的顺序出现,stdout 表现得“好像”它遵守C规则。

如果您担心性能,那么您可能想要运行一些 试验。尝试测量输出到std::ofstream所需的时间 你已经打开了自己,而不是输出到的时间 std::cout(无论是否有sync_with_stdio), 输出重定向。差异应该很有趣。

答案 2 :(得分:9)

C ++标准将所有输入和输出定义为“好像”所有读取和写入最终都是通过C流的读取和写入发生的([iostream.objects.overview]):

  

标头声明了将对象与(27.9.2)中声明的函数提供的标准C流相关联的对象,并包括使用这些对象所需的所有标头。

对于附加到这些对象的标准C流的行为,我们必须参考C标准(第7.19.3节):

  

在程序启动时,预定义了三个文本流,无需显式打开    - 标准输入(用于读取传统输入),标准输出(用于写入)   常规输出)和标准错误(用于写入诊断输出)。最初   打开后,标准错误流未完全缓冲;标准输入和标准   当且仅当可以确定流不被引用时,输出流被完全缓冲   到交互设备。

这里我引用了C99标准,但我可以肯定地确定(部分编号的模数变化)与C标准的所有版本相同。

答案 3 :(得分:2)

从我从here读取的内容来看,cout通常是缓冲的,但是当它检测到它打印到交互式环境(如控制台)时,它会回退到无缓冲的状态。

因此,如果您重定向输出(在UNIX中使用'&gt;'),则缓冲行为将启动。

链接帖子中的更多详细信息。

答案 4 :(得分:2)

根据这个页面 - http://www.programmingincpp.com/flush-the-output-stream-buffer.html - std :: cout被缓冲。我有一些东西无法打印,因为在cout&lt;&lt;&lt;&lt;&lt;&lt;&lt; ...声明但在它被刷新之前:

cout << "My error or flag message, but it's not flushed, so I never see it";

//system crash!

cout << endl;