std::cout 是否已缓冲?

问题描述 投票:0回答:5

刚刚阅读“Scott Meyers”的一篇古老但有趣的文章

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

基本上是关于更喜欢使用

'\n'
而不是
std::endl
(我同意并且多年来一直使用相同的增强)。

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

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

我快速浏览了一下,但找不到

1
的明确标准参考。
std::cout
无缓冲与我一直以来的理解相悖吗?

c++ cout
5个回答
25
投票

是的,已缓冲:

C++11 27.4.2 [narrow.stream.objects]/3 :对象

cout
控制与对象
stdout

关联的流缓冲区的输出

本文引用了 C++98 标准的 1995 年草案版本。我不知道这是否会表达不同的意思。

对于第 2 点,

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


12
投票

首先,不要求

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
), 输出重定向。 这些差异应该很有趣。


10
投票

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

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

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

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

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


2
投票

根据此页面 - 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;

2
投票

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

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

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

© www.soinside.com 2019 - 2024. All rights reserved.