刚刚阅读“Scott Meyers”的一篇古老但有趣的文章
http://aristeia.com/Papers/C++ReportColumns/novdec95.pdf
基本上是关于更喜欢使用
'\n'
而不是std::endl
(我同意并且多年来一直使用相同的增强)。
但是最后一部分表明这没有包含在他的书中,因为整个事情因两点而变得毫无意义:
std::cout
未缓冲。ios::unitbuf
的状态没有明确定义(因此依赖于实现)。我快速浏览了一下,但找不到
1
的明确标准参考。 std::cout
无缓冲与我一直以来的理解相悖吗?
是的,已缓冲:
C++11 27.4.2 [narrow.stream.objects]/3 :对象
控制与对象cout
关联的流缓冲区的输出stdout
本文引用了 C++98 标准的 1995 年草案版本。我不知道这是否会表达不同的意思。
对于第 2 点,
unitbuf
在所有流上最初都是 false(由 basic_ios
构造函数的后置条件指定),除了 cerr
和 wcerr
明确指定其他情况。同样,这在所提到的古代草案中很可能有所不同。
首先,不要求
std::cout
(甚至 std::cerr
)是
无缓冲。 唯一的要求是 std::cerr
有
std::basic_ios::unitbuf
设置(这样它就会在每次结束时齐平)
输出函数:<<
或非格式化输出函数)。 另一方面
手,除非你打电话给std::basic_ios::sync_with_stdio(false)
,
输出到C++流并输出到相应的
C 流(即 std::cout
和 stdout
)必须具有相同的效果。
理论上,这可以通过多种方式完成: stdout
函数可以
转发到 std::cout
,std::cout
输出可以转发到
stdout
,或者他们可以在以下共享一些常见的缓冲区实现
兜帽。 在实践中,几乎所有的实现都有std::cout
转发至stdout
。
C 指定
stderr
未完全缓冲,并且 stdout
可能
仅当可以确定不引用某个对象时才进行完全缓冲
交互设备(对于某些实现定义的含义
“交互设备”)。 通常,stdout
将进行行缓冲(a
iostream 中不存在的概念),并且 stderr
将是
无缓冲,但这不是 C 标准所保证的(并且可能不是
今天确实如此——我最后一次真正看已经是二十多年了
前)。 无论如何,仅转发到 stdout
的实现将
遵循它转发到的 C 实现的规则,并且
不'仍然需要采取一些步骤来确保输出到
std::cout
和 stdout
按正确的顺序出现,并且 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 标准的所有版本中都是相同的。
根据此页面 - http://www.programmingincpp.com/flush-the-output-stream-buffer.html - std::cout 被缓冲。 我遇到了一些无法打印的问题,因为在 cout 之后发生了程序崩溃 << ... statement but before it was flushed:
cout << "My error or flag message, but it's not flushed, so I never see it";
//system crash!
cout << endl;
从我读到的表格here来看,cout通常是缓冲的,但是当它检测到它打印到交互式环境(如控制台)时,它会回落到无缓冲状态。
因此,如果您重定向输出(在 UNIX 中使用“>”),则缓冲行为就会启动。
链接帖子中有更多详细信息。