2011-05-17 73 views
7
#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; 
} 

的缓冲后,我编译和运行上面的程序,它的输出是:为什么CERR刷新COUT

hello couthello cerr 
All done 

,但我认为它应该是:

hello cerrhello cout 
All done 

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

+0

'cout <<“hello cout”;'before before'cerr <<“hello cerr”;' – iammilind 2011-05-17 06:28:37

+0

我想知道为什么cout的输出会在cerr之前出现。我认为cout的输出是缓冲的,cerr的输出应该先出来 – wildpointercs 2011-05-17 06:30:58

回答

7

这是设计。

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

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

+0

这是错误的。 'cout'绑定到'cin',但就是这样。 'cerr'不受任何束缚,也没有任何束缚。 (这并不意味着该实现不使用其他同步机制,但是需要'cerr.tie()'来返回一个空指针。) – 2011-05-17 08:12:00

+0

快速检查显示VC8在这里有一个错误:'cerr.tie ()'返回非null,尽管这是C++标准明确禁止的。 (g ++正确) – 2011-05-17 08:16:31

+0

@James - 在我的草稿副本中写道:“在对象cerr初始化后,cerr.flags()&unitbuf'为非零,'cerr.tie()'返回'&cout' “。 (27.4.2) – 2011-05-17 08:18:34

7

首先,一个流只要感觉就可以刷新。我有可能在输出到交互设备时,iostream的某些实现会改变缓冲策略。除非有意在两个数据流的输出之间进行刷新,否则它们出现的顺序或多或少都是未指定的;所有你可以指望的是,一个<<cerr将不会有从cout插入到其中的字符。在你的情况下,实现以某种方式同步coutcerr。 (您可能希望看到如果将输出重定向到不同的文件会发生什么,或者到同一个非交互式文件— C++没有区分交互设备和其他设备,但是C可以,我希望大多数C++实现遵循C in 。这方面)

FWIW,就为了这两个保证是:

  • cout绑定到cin,因此任何试图在cin阅读将刷新cout,并且
  • cerrunitbuf集,因此这将是 在每个<<运营商的末尾刷新。

背后后者的想法是,我认为,以获得类似于C的行缓冲的东西,这虽然如果你使用std::endl,你为行缓冲的效果相同的C++不直接支持—。