clog:控制输出,使其输出到一个缓冲区,这个缓冲区关联着定义在 <cstdio> 的 stderr。

cerr:强制输出刷新,没有缓冲区。

cout:控制输出,使其输出到一个缓冲区,这个缓冲区关联着定义在 <ostream> 的 stdout。

但是我们分别测试如下三个程序的结果如下:

cout:

#include <iostream>

using namespace std;

int main(int argc, char const *argv[])
{
cout << "ERROR!!";
while (true);
return ;
}

输出结果为:

    

可以理解,因为 cout 输出是有缓冲区的,这里没有输出说明缓冲区还没有刷新。

cerr:

#include <iostream>

using namespace std;

int main(int argc, char const *argv[])
{
cerr << "ERROR!!";
while (true);
return ;
}

输出:

    

可以理解,因为 cerr 没有输出缓冲区,是强制刷新的,所以在循环之前就已经刷新了,所以会打印结果。

clog:

#include <iostream>

using namespace std;

int main(int argc, char const *argv[])
{
clog << "ERROR!!";
while (true);
return ;
}

输出:

    

这个比较奇怪,不是说 clog 是由缓冲区的嘛,为什么它不是像 cout 一样的输出呢?先看下面部分:

对于cout,clog,cerr输出的机制,c跟c++的标准做法是:

stderr : 预设没有分配 buffer

stdout :预设有分配 buffer

cout :用 stdout 的buffer

clog :用 stderr 的 buffer

cerr :用 stderr 的buffer,强制清空 buffer

其中,stderr 的 buffer 预设为没有,所以 clog 和 cerr 都是直接在屏幕输出而没有在缓冲区驻留。所以前面 clog 的输出结果也就可以理解了,因为缓冲区是空的,那么输出就不会在缓冲区驻留了。

下面来说说 cout,clog,cerr 的输出顺序,也可作为 clog 一个更深入的理解。

先看下面一段代码:

#include <iostream>

using namespace std;

int main(int argc, char const *argv[])
{
setbuf(stderr,);
cout << "";
clog << "";
cerr << ""; return ;
}

它的输出结果是:

  456123789

上面代码中,setbuf 为 0,也就是设置 stderr 的缓冲区为 0,因为 stderr 的值是有可能因为编译器的不同而不同的,前面说的 c++ 机制只是标准机制,编译器实现商可以进行自己的改变的。

现在来理解一下输出的结果,首先 clog 的输出在最前面很容易理解,但是为什么 cout 的输出在 cerr 的前面呢,因为cerr 的输出关联到了 cout,也即 cerr.tie()=&cout,所以当 cerr 要清空时,会先清空前面的 cout 的缓冲区。[注意只是 cerr 前面的 cout ]

看另一段代码:

#include <iostream>

using namespace std;

char buf[];
int main(int argc, char const *argv[])
{
setbuf(stderr,buf);
cout << "";
clog << "";
cerr << ""; return ;
}

此时的输出是:

  123456789

在这里给 stderr 的缓冲区设为了 buf,不再是 0 了,所以这里输出结果按顺序输出。

下面取消 cerr 和 cout 的关联:

#include <iostream>

using namespace std;

char buf[];
int main(int argc, char const *argv[])
{
cerr.tie();
setbuf(stderr, buf);
cout << "";
clog << "";
cerr << ""; return ;
}

输出结果为:

  456789123

这里 clog 在 cout 前面输出,因为 cerr 输出的时候强制刷新了 stderr 缓冲区。

cerr 和 clog 位置调换,结果为:

#include <iostream>

using namespace std;

char buf[];
int main(int argc, char const *argv[])
{
cerr.tie();
setbuf(stderr, buf);
cout << "";
cerr << "";
clog << ""; return ;
}

输出结果:

  789123456

此时 cerr 最先输出,因为强制刷新,而 clog 因为缓冲区不为空,所以会在程序结束的时候执行 flush。

再来说说 clog 和 cerr 的重定向问题。

直接对 cerr 和 clog 的输出使用重定向符 > 是无效的,这两个的输出一定会打印在终端上,但是如果一定要进行重定向,那么可以用  rdbuf 函数,如下:

ofstream ofs("logfile");
clog.rdbuf(ofs.rdbuf());
clog << "Goes to file." << endl;

以上测试结果都是在mac g++4.2.1 测试的结果,输出结果在mac的终端。在windows下面测试的结果可能不同。

具体的区别可以参考如下内容:【以下内容来源:http://tieba.baidu.com/p/937433213】

1.该物件所用的stream是否按照规定分配buffer
全缓冲:buffer满了才执行fflush()
行缓冲:buffer满了or碰到换行字元才执行fflush()
无缓冲:不管buffer有没有满都执行fflush()

console下
            标准     windows    linux
stdout| 行/无缓冲|全缓冲   |行缓冲    |
stderr| 行/无缓冲|全缓冲   |无缓冲    |

非console
            标准      windows   linux
stdout|  全缓冲    |全缓冲   |全缓充    |
stderr|  行/无缓冲|全缓冲   |无缓冲    |

以上是预设值,有一点要厘清,全/行/无缓冲只是该stream的特性,
与它有没有buffer并没有关系,拿windows来说,
乍看之下会等到buffer满才输出,但实际上是直接输出,
因为没有分配buffer,你也可以对无缓冲的stream分配buffer,
虽然一样直接跑fflush()就是了

如果要分配buffer给stream,可以用setbuf()和setvbuf(),
用前者时要注意,一但用它分配buffer后,行缓冲的特性会消失,
且buffer不能是局部变量,因为最后一次fflush()是在exit()里执行
那时局部变量已经被释放

2.该物件是否按照规定设置ios::unitbuf
如果有设ios::unitbuf,就直接执行fflush(),
即使底下stream设成全缓冲跟分配buffer也一样,
除非手动设定,否则只有cerr才有设ios::unitbuf

如果要修改物件的ios::unitbuf,可用setf()或unsetf()设定

3.该物件的是否按照规定绑定别的物件

标准  windows  linux
clog.tie()| null |&cout|   null |
cerr.tie()|&cout|&cout|  &cout|
cout.tie()|null  | null  |    null |

如果有绑别的物件,当自己准备要跑fflush()时,
会先让被绑定的物件执行fflush(),然后才换自己跑fflush()

如果要修改绑定的物件,就用tie()来设,传0代表不绑定

虽然下列网站写cin、cerr、clog都绑定cout, 
http://www.cplusplus.com/reference/iostream/ios/tie/
但是C++的规格书上,其实没规定clog要绑cout

4.换行字元跟endl
前者只能让行缓冲的物件跑fflush(),
后者则强迫cout、cerr、clog跑fflush()

5.如果一直到main()结束都没有跑fflush()
那么stdout会先输出,接著才是stderr

7.main()结束后,不可再用cout、cerr、clog来输出
首先来看exit()的标准流程

A.摧毁thread物件
B.摧毁global物件/摧毁函式里的static物件/执行atexit注册函式
C.让所有的C stream执行fflush(),接著关闭它们
D.砍掉暂存档
E.归还控制权给OS

在执行dtor/atexit注册函式时,无法保证cout、cerr、clog这些物件还在

总结:
没分配buffer、无缓冲、ios::unitbuf!=0、buffer已满、行缓冲碰到'\n'、endl
以上只要有一个成立就会跑fflush()

clog,cout,cerr 输出机制的更多相关文章

  1. C++ cout cerr 和 clog 的区别

    我们都知道C++预定义了cin(标准输入流)和cout(标准输出流).但今天突然又蹦出来两个cerr(标准错误流(非缓冲))和clog(标准错误流(缓冲)),本着学习提高的态度在网上搜索了相关内容,下 ...

  2. 转:c++里关于cerr,clog,cout三者的区别

    c++里关于cerr,clog,cout三者的区别: cerr(无缓冲标准错误)-----没有缓冲,发送给它的内容立即被输出 clog(缓冲标准错误)--------有缓冲,缓冲区满时输出 cout- ...

  3. C++输入cout与输出cin

    输入和输出并不是C++语言中的正式组成成分.C和C++本身都没有为输入和输出提供专门的语句结构.输入输出不是由C++本身定义的,而是在编译系统提供的I/O库中定义的.C++的输出和输入是用" ...

  4. std::cout彩色输出

    Mac OS效果 Windows 效果 想写这个东西其实是因为最近要写个命令行的工具,但是有个问题是什么呢?就是传统的那个黑漆漆的窗口看起来很蛋疼.并且完全看不到重点,于是就想起 来这么一个东西.相对 ...

  5. C++ cout格式化输出(转)

    C++ cout格式化输出(转) 这篇文章主要讲解如何在C++中使用cout进行高级的格式化输出操作,包括数字的各种计数法(精度)输出,左或右对齐,大小写等等.通过本文,您可以完全脱离scanf/pr ...

  6. OpenEXR的输出机制

    最近在一直在研究OpenEXR这个软件.这个软件的图像输出机制很有意思,特地分享一下学习心得,就当是笔记了. 我的OpenEXR软件版本是2.2.0,系统平台是win7. 安装完毕OpenEXR之后我 ...

  7. 使用std::cout不能输出显示

    在测试一行函数时,出现std::cout不能输出的情况,找不到原因. 1.         只好从main函数第一行,开始测试,直到发现一个函数 o_Initer.ekf_filter(filter, ...

  8. fork以后子进程输出cout无法输出

    fork以后子进程输出cout无法输出 fork以后子进程输出cout无法输出 子进程 fork  cout<<"sdfsf"<<endl; 内容无法输出控 ...

  9. Cocos2d-x之Log输出机制

    |   版权声明:本文为博主原创文章,未经博主允许不得转载. 在cocos2d-x中,我们使用log这个函数进行输出,log可以输出很多参数,它的使用方式就和使用c语言中的printf的使用方式差不多 ...

随机推荐

  1. elasticsearch使用More like this实现基于内容的推荐

    基于内容的推荐通常是给定一篇文档信息,然后给用户推荐与该文档相识的文档.Lucene的api中有实现查询文章相似度的接口,叫MoreLikeThis.Elasticsearch封装了该接口,通过Ela ...

  2. Error:Artifact 'xx.war exploded' has invalid extension

    环境信息:  IDEA 13 ,  MAVEN, JBOSS 7. 配置信息: 常规配置. 出错信息: Error:Artifact 'xx.war exploded' has invalid ext ...

  3. 【刷题】BZOJ 2005 [Noi2010]能量采集

    Description 栋栋有一块长方形的地,他在地上种了一种能量植物,这种植物可以采集太阳光的能量.在这些植物采集能量后,栋栋再使用一个能量汇集机器把这些植物采集到的能量汇集到一起. 栋栋的植物种得 ...

  4. 【转】器件为什么只听英文Datasheet的话

    浅谈为什么要阅读英文数据手册 ——带你Go Through Datasheet 系列 Unfortunately!从事软硬件(固件)开发的工程师都知道,我们所用的元器件,特别是高端器件和芯片,都是来自 ...

  5. 在OpenShift上托管web.py应用

    一.背景 最近在学习web.py,跟随官网的cookbook和code examples一路敲敲打打,在本地访问了无数遍http://0.0.0.0:8080/,也算是对web.py有了基本的认识.为 ...

  6. 一次lvs迁移记录

    需求:从117.119.33.99迁移到122.14.206.125,lvs为dr模式,系统版本为debian7 1.安装lvs和keepalived # aptitude install -y ip ...

  7. php实践

    http://blog.csdn.net/apanious/article/details/51075899

  8. Android Studio 换主题(Material Theme..)

    1.去如下网址下载自己喜欢的主题文件xx.jar http://color-themes.com/?view=index 2. 导入方式 下载主题—xxx.jar 注意:如果我们下载下来的jar名字如 ...

  9. CSS3 grayscale滤镜+SVG使图片变黑白实例页面

    CSS代码: .gray { -webkit-filter: grayscale(100%); -moz-filter: grayscale(100%); -ms-filter: grayscale( ...

  10. 【位运算】判断一个数是否为2的n次方

    import java.util.Scanner; /** * 功能:用位运算,判断一个数是否为2的n次方. * 思路:用1做移位操作,然后判断移位后的值是否与给定的数相同. */ public cl ...