clog,cout,cerr 输出机制
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 输出机制的更多相关文章
- C++ cout cerr 和 clog 的区别
我们都知道C++预定义了cin(标准输入流)和cout(标准输出流).但今天突然又蹦出来两个cerr(标准错误流(非缓冲))和clog(标准错误流(缓冲)),本着学习提高的态度在网上搜索了相关内容,下 ...
- 转:c++里关于cerr,clog,cout三者的区别
c++里关于cerr,clog,cout三者的区别: cerr(无缓冲标准错误)-----没有缓冲,发送给它的内容立即被输出 clog(缓冲标准错误)--------有缓冲,缓冲区满时输出 cout- ...
- C++输入cout与输出cin
输入和输出并不是C++语言中的正式组成成分.C和C++本身都没有为输入和输出提供专门的语句结构.输入输出不是由C++本身定义的,而是在编译系统提供的I/O库中定义的.C++的输出和输入是用" ...
- std::cout彩色输出
Mac OS效果 Windows 效果 想写这个东西其实是因为最近要写个命令行的工具,但是有个问题是什么呢?就是传统的那个黑漆漆的窗口看起来很蛋疼.并且完全看不到重点,于是就想起 来这么一个东西.相对 ...
- C++ cout格式化输出(转)
C++ cout格式化输出(转) 这篇文章主要讲解如何在C++中使用cout进行高级的格式化输出操作,包括数字的各种计数法(精度)输出,左或右对齐,大小写等等.通过本文,您可以完全脱离scanf/pr ...
- OpenEXR的输出机制
最近在一直在研究OpenEXR这个软件.这个软件的图像输出机制很有意思,特地分享一下学习心得,就当是笔记了. 我的OpenEXR软件版本是2.2.0,系统平台是win7. 安装完毕OpenEXR之后我 ...
- 使用std::cout不能输出显示
在测试一行函数时,出现std::cout不能输出的情况,找不到原因. 1. 只好从main函数第一行,开始测试,直到发现一个函数 o_Initer.ekf_filter(filter, ...
- fork以后子进程输出cout无法输出
fork以后子进程输出cout无法输出 fork以后子进程输出cout无法输出 子进程 fork cout<<"sdfsf"<<endl; 内容无法输出控 ...
- Cocos2d-x之Log输出机制
| 版权声明:本文为博主原创文章,未经博主允许不得转载. 在cocos2d-x中,我们使用log这个函数进行输出,log可以输出很多参数,它的使用方式就和使用c语言中的printf的使用方式差不多 ...
随机推荐
- elasticsearch使用More like this实现基于内容的推荐
基于内容的推荐通常是给定一篇文档信息,然后给用户推荐与该文档相识的文档.Lucene的api中有实现查询文章相似度的接口,叫MoreLikeThis.Elasticsearch封装了该接口,通过Ela ...
- Error:Artifact 'xx.war exploded' has invalid extension
环境信息: IDEA 13 , MAVEN, JBOSS 7. 配置信息: 常规配置. 出错信息: Error:Artifact 'xx.war exploded' has invalid ext ...
- 【刷题】BZOJ 2005 [Noi2010]能量采集
Description 栋栋有一块长方形的地,他在地上种了一种能量植物,这种植物可以采集太阳光的能量.在这些植物采集能量后,栋栋再使用一个能量汇集机器把这些植物采集到的能量汇集到一起. 栋栋的植物种得 ...
- 【转】器件为什么只听英文Datasheet的话
浅谈为什么要阅读英文数据手册 ——带你Go Through Datasheet 系列 Unfortunately!从事软硬件(固件)开发的工程师都知道,我们所用的元器件,特别是高端器件和芯片,都是来自 ...
- 在OpenShift上托管web.py应用
一.背景 最近在学习web.py,跟随官网的cookbook和code examples一路敲敲打打,在本地访问了无数遍http://0.0.0.0:8080/,也算是对web.py有了基本的认识.为 ...
- 一次lvs迁移记录
需求:从117.119.33.99迁移到122.14.206.125,lvs为dr模式,系统版本为debian7 1.安装lvs和keepalived # aptitude install -y ip ...
- php实践
http://blog.csdn.net/apanious/article/details/51075899
- Android Studio 换主题(Material Theme..)
1.去如下网址下载自己喜欢的主题文件xx.jar http://color-themes.com/?view=index 2. 导入方式 下载主题—xxx.jar 注意:如果我们下载下来的jar名字如 ...
- CSS3 grayscale滤镜+SVG使图片变黑白实例页面
CSS代码: .gray { -webkit-filter: grayscale(100%); -moz-filter: grayscale(100%); -ms-filter: grayscale( ...
- 【位运算】判断一个数是否为2的n次方
import java.util.Scanner; /** * 功能:用位运算,判断一个数是否为2的n次方. * 思路:用1做移位操作,然后判断移位后的值是否与给定的数相同. */ public cl ...