是 std::cout 缓冲的

Is std::cout buffered?

本文关键字:缓冲 cout std      更新时间:2023-10-16

只是在读"斯科特·迈耶斯"的一篇古老但有趣的文章

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

基本上,这是关于更喜欢使用'n'而不是std::endl(我同意并且多年来一直使用相同的增强)。

但是最后一节表明这没有包括在他的书中,因为整件事由于两点而变得毫无意义:

  1. std::cout未缓冲。
  2. std::cout 上的ios::unitbuf状态没有明确定义(因此依赖于实现)。

我快速浏览了一下,但找不到明确的标准参考1这是真的。std::cout无缓冲是否与我一直理解的相反?

是的,它是缓冲的:

C++11 27.4.2 [窄流对象]/3 :对象cout控制输出到与对象stdout关联的流缓冲区

这篇文章提到了1995年成为C++98标准的草案版本。我不知道这是否可能说了一些不同的东西。

至于第 2 点,unitbuf 最初在所有流上都是 false(由 basic_ios 构造函数的后置条件指定),除了明确指定其他内容的 cerrwcerr。同样,在所提到的古代草案中,情况很可能有所不同。

首先,不要求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将被行缓冲(aIOstream中不存在的概念),stderr将是无缓冲,但 C 标准不能保证(并且可能不是今天是真的——我最后一次真正看是二十多年前)。 无论如何,一个转发给stdout的实现将遵循它转发到的 C 实现的规则,并且不需要"仍然需要采取一些步骤来确保输出到 std::coutstdout以正确的顺序出现,这stdout行为"好像"它遵守了 C 规则。

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

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

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

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

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

在这里,我引用的是 C99 标准,但我有理由确定(节编号的模数变化)在所有版本的 C 标准中都是相同的。

从我在这里读到的形式来看,cout 通常是缓冲的,但是当它检测到它打印到交互式环境(如控制台)时,它会回退到未缓冲状态。

因此,如果您重定向输出(使用 UNIX 中的">"),则缓冲行为就会启动。

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

根据这个页面 - http://www.programmingincpp.com/flush-the-output-stream-buffer.html - std::cout是缓冲的。 我有一些东西无法打印,因为在 cout <<之后发生了程序崩溃......语句,但在刷新之前:

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