【问题标题】:Is std::cout buffered?std::cout 是否缓冲?
【发布时间】:2014-11-17 15:19:51
【问题描述】:

刚刚阅读了“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


【解决方案1】:

是的,它被缓冲了:

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

这篇文章引用了 1995 年 C++98 标准的草案版本。我不知道这是否会说不同的东西。

至于第 2 点,unitbuf 在所有流上最初为 false(由 basic_ios 构造函数的后置条件指定),但 cerrwcerr 除外,它们明确指定了其他方式。同样,这在所引用的古代草案中很可能有所不同。

【讨论】:

  • 我看到了。但是,如果您阅读下一段。它对未缓冲的 std:cerr 说了同样的话。所以我不相信buffer 这个词在这里没有被超载。 The object cerr controls output to a stream buffer associated with the object stderr
  • @LokiAstari: cerr 也被缓冲了。不同之处在于它设置了unitbuf,所以它在每一行之后自动刷新。
  • 好的。这是有道理的。
  • (“行”是指“操作”。现在修复评论为时已晚。)
  • 流缓冲区实际上不需要做任何缓冲。
【解决方案2】:

首先,没有要求std::cout(甚至std::cerr)是 无缓冲。唯一的要求是std::cerrstd::basic_ios::unitbuf 设置(以便在每个结束时刷新 输出函数:<< 或非格式化输出函数)。在另一 手,除非你打电话给std::basic_ios::sync_with_stdio(false), 输出到 C++ 流并输出到相应的 C 流(即std::coutstdout)必须具有相同的效果。 理论上,这可以通过多种方式完成:stdout 函数可以 转发到std::coutstd::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), 输出重定向。差异应该很有趣。

【讨论】:

    【解决方案3】:

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

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

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

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

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

    【讨论】:

    • 从记忆中看,这个从C90开始就没有变过,和原始Unix手册对C的要求相对应。另一方面,他问的是C++,C++有不同的规则。 (特别是,C++ 没有行缓冲的概念。)
    【解决方案4】:

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

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

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

    【讨论】:

    • 您混淆了stdoutstd::cout。前者对终端进行行缓冲,否则进行块缓冲。
    • 我说的和Jerry Coffin一样,都是用C99标准写的。
    • 我认为 C99 标准中没有提到 std::cout
    • 确实如此。对不起。但即便如此,我认为stdout的标准体现在std::cout中。
    • @nighthawk702 没有要求,只要输出到stdcout 的顺序正确,并且遵守C 中指定的规则。
    【解决方案5】:

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

    【讨论】:

      猜你喜欢
      • 2020-01-20
      • 1970-01-01
      • 2020-12-12
      • 2019-03-05
      • 2011-11-04
      • 1970-01-01
      • 1970-01-01
      • 2020-07-12
      • 2014-10-30
      相关资源
      最近更新 更多