【问题标题】:why cerr flushes the buffer of cout为什么 cerr 刷新 cout 的缓冲区
【发布时间】:2011-08-26 23:44:41
【问题描述】:
#include <iostream>
using std::cout;
using std::endl;
using std::cerr;
#include <cstdio>

int   main( )
{
    char pbuffer[BUFSIZ];
    setbuf(stdout, pbuffer);
    cout << "hello cout" ;
    sleep(5);
    cerr << "hello cerr";
    sleep(5);
    cout << "\nAll   done " << endl;
    sleep(5);
    return 0;
}

我编译并运行上面的程序后,它的输出是:

hello couthello cerr
All   done 

但我认为应该是:

hello cerrhello cout
All   done 

我想知道,为什么cerr会刷新cout的缓冲区?

【问题讨论】:

  • cout &lt;&lt; "hello cout";cerr &lt;&lt; "hello cerr"; 之前
  • 我想知道为什么 cout 的输出在 cerr 之前。我认为cout的输出是缓冲的,cerr的输出应该先出来

标签: c++


【解决方案1】:

这是设计使然。

cincerr 都绑定到 cout,并在它们自己的任何操作之前调用 cout.flush()。

这个想法可能是输入和输出应该以正确的顺序发生。

【讨论】:

  • 这是错误的。 coutcin 绑定,仅此而已。 cerr 与任何事物无关,也与任何事物无关。 (这并不意味着该实现没有使用其他同步机制。但cerr.tie() 需要返回一个空指针。)
  • 快速检查显示 VC8 在这里有一个错误:cerr.tie() 确实返回非空值,尽管 C++ 标准明确禁止这样做。 (g++ 做对了。)
  • @James - 在我的草稿副本中说“初始化对象 cerr 后,cerr.flags() &amp; unitbuf 非零且cerr.tie() 返回&amp;cout。” (27.4.2)
  • 我正在查看实际的 ISO C++ 2003 标准,它说“在初始化对象 cerr 后,cerr.flags() & unitbuf 为非零。它的状态与 @ 所需的其他状态相同987654333@tie() == 0. I see that later drafts have changed this---yet another incompatibility to deal with. (Not a serious one, however, since as far as I can see, cout` 和 cerr 实际上可以共享相同的 streambuf,这会更加同步。)
  • cerr 现在 绑定到 cout - 引用 en.cppreference.com/w/cpp/io/cerr - 此外,std::cerr.tie() 返回 &amp;std::cout(对于`wcerr` 和 @987654341 @),表示对std::cerr 的任何输出操作首先执行std::cout.flush()(通过std::basic_ostream::sentry 的构造函数)(C++11 起)。
【解决方案2】:

首先,流可以随时刷新。我可能在输出到交互式设备时,iostream 的某些实现确实会更改缓冲策略。除非您有意在两个流的输出之间刷新,否则它们出现的顺序或多或少是未指定的;您可以指望的是,单个&lt;&lt;cerr 不会插入来自cout 的字符。在您的情况下,实现以某种方式同步 coutcerr。 (您可能想看看如果将它们的输出重定向到不同的文件会发生什么。或者到同一个非交互式文件 - C++ 不区分交互式设备和其他设备,但 C 有,我希望大多数 C++ 实现遵循 C尊重。)

FWIW,关于订单的两个保证是:

  • coutcin 绑定,因此任何对 cin 的读取尝试都会刷新 cout,并且
  • cerr 设置了 unitbuf,因此它将在每个 &lt;&lt; 运算符的末尾刷新。

我认为,后者背后的想法是获得类似于 C 的行缓冲的东西,而 C++ 并不直接支持该功能——尽管如果您使用 std::endl,您将获得与行缓冲相同的效果。

【讨论】:

    猜你喜欢
    • 2020-04-06
    • 2022-10-02
    • 1970-01-01
    • 2020-01-18
    • 2013-02-09
    • 1970-01-01
    • 2011-11-04
    • 2021-11-19
    • 2020-12-12
    相关资源
    最近更新 更多