cout/cerr/clog之异同极其重定向

本文深入探讨了C++中cout、cerr、clog输出流对象的功能、特点及区别,并详细讲解了它们的重定向方法,通过实例演示外部和内部重定向,解释了为何C++会定义三个功能相似但用途不同的输出流对象,旨在提升代码可读性和程序健壮性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最近刚入手了一本《C++ Primer(第五版)》,开始按照C++0x的标准把之前积累的C++知识重头梳理一遍。在看到“初识输入输出”这一小节时,见书中提到了cout/cerr/clog三个输出对象,但说得又不分明,于是百度了一下,学习了这三者间的异同以及重定向方法,但同时又发现网上关于重定向的说法和我的实测结果不吻合,故总结为此文,与大家交流讨论。

 

C++iostream库中定义了4IO对象,除1个标准输入对象cin之外,其余3个都是输出对象,它们分别是:

cout:又叫标准输出;

cerr:又叫标准错误;

clog:难道叫“标准日志”?没见过有哪本书上如此为它命名。

 

它们的共同点

1. cout/cerr/clog都不是C++预定义的关键字,它们是ostream流类的对象,在iostream中定义(iostream库包含两个基础类型istreamostream,分别表示输入流和输出流)。

2. 它们都是用来在屏幕上显示一段文字信息,这些信息都是写到同一个窗口。

3. 它们都可以把信息重定向输出到磁盘文件,包括外部重定向和内部重定向(详见最后两个例子)。

它们的不同点

1. cout与clog流在内存中对应开辟了一个缓冲区,用来存放流的数据,当向cout流插入一个endl时,不论缓冲区是否已满,都立即输出流中所有数据,然后插入一个换行符。

2. cerr流所输出信息不经过缓冲区,直接输出给屏幕。

 

关于它们共同点中的第3条,这里有两个示例,分别演示了如何进行外部和内部重定向。

1. 外部重定向:

假设有如下代码:

#include<iostream>
int main()
{
	std::cout<<"cout"<<std::endl;
	std::cerr<<"cerr"<<std::endl;
	std::clog<<"clog"<<std::endl;
	return 0;
}

编译生成D:\EX01.exe。在cmd中执行命令:

D:\>EX01.exe

屏幕上输出:

cout

cerr

clog

若执行命令D:\>EX01.exe > D:\ex01.txt 或执行 D:\>EX01.exe 1> D:\ex01.txt

屏幕上输出:

cerr

clog

而文本“cout”已经被重定向输出到了D:\ex01.txt中。

若执行命令D:\>EX01.exe 2> D:\ex01.txt

屏幕输出:

cout

此时,文本“cerr”和“clog”都被重定向输出到了D:\ex01.txt中。



例2. 内部重定向

下面以对cerr输出流的重定向为例,cout和clog也可同样操作。

#include <iostream>
#include <fstream>
using namespace std;
int main()
{
	ofstream file("D:\\ex01.txt");
	streambuf *err = cerr.rdbuf(file.rdbuf());
	cerr << "cerr1" <<endl;
	cerr.rdbuf(err);
	cerr << "cerr2" <<endl;
	return 0;
}

由以上可知,cout/cerr/clog三者功能都差不多,既然如此,那为什么C++会定义三个功能相当的对象呢?我一开始的粗浅见解是:这是为了提高程序的可读性而设计的,当我们在维护代码时,看到cout就知道是一般性的输出,看到cerr就知道这里是要输出一个错误信息,看到clog,也许就是要输出一般性的日志信息。后来又在优快云上找到一篇文章,感觉他说得比我专业,比我正确,故引用于此,这里是原文链接:

http://blog.youkuaiyun.com/mengxiangying504/article/details/5008841

对于为什么有cerr和clog
比如,你的程序遇到调用栈用完了的威胁(无限,没有出口的递归)。
你说,你到什么地方借内存,存放你的错误信息?
所以有了cerr。其目的,就是在你最需要它的紧急情况下,还能得到输出功能的支持。
缓冲区的目的,就是减少刷屏的次数——比如,你的程序输出圣经中的一篇文章。不带缓冲的话,就会每写一个字母,就输出一个字母,然后刷屏。有了缓冲,你将看到若干句子“同时”就出现在了屏幕上(由内存翻新到显存,然后刷新屏幕)。

### C++ iostream 中 `cin`、`cout`、`cerr` 和 `clog` 的区别与应用场景 #### 输入输出流概述 C++ 提供了四个主要的标准输入输出流对象:`cin`、`cout`、`cerr` 和 `clog`。这些对象分别用于不同的用途,具有各自的特点。 --- #### 1. **`cin`** - `cin` 是标准输入流 (Standard Input Stream),通常绑定到键盘。 - 它允许程序从外部获取数据,主要用于交互式应用程序。 - 使用方式简单直观,通过提取操作符 (`>>`) 获取用户输入的数据。 示例代码: ```cpp #include <iostream> using namespace std; int main() { int number; cout << "Enter a number: "; cin >> number; // 用户输入存储到变量中 cout << "You entered: " << number << endl; return 0; } ``` --- #### 2. **`cout`** - `cout` 是标准输出流 (Standard Output Stream),默认绑定到屏幕。 - 主要功能是将信息显示给用户。 - 输出可以通过管道或其他机制重定向到文件或设备。 特点: - 支持格式化输出。 - 可以被重定向到其他目标(如文件),而不局限于显示器。 示例代码: ```cpp #include <iostream> using namespace std; int main() { cout << "This is standard output." << endl; // 显示消息 return 0; } ``` --- #### 3. **`cerr`** - `cerr` 是标准错误流 (Standard Error Stream),也绑定到屏幕。 - 特点是没有缓冲区支持,即每次写入的内容会立即发送到终端,不会等待缓冲区填满再刷新。 - 常用于报告运行时错误或异常情况的信息。 特点: - 不可重定向[^3]。 - 数据直接输出至控制台,无需额外处理。 示例代码: ```cpp #include <iostream> using namespace std; int main() { cerr << "An error occurred!" << endl; // 错误提示 return 1; } ``` --- #### 4. **`clog`** - `clog` 同样是一个标准错误流 (Standard Logging Stream)。 - 跟 `cerr` 类似,但它使用缓冲区来暂存数据,只有当缓冲区满了或者遇到换行符时才会实际输出内容。 - 这种特性使得它适合记录日志信息,在性能敏感的情况下更为高效。 特点: - 可以被重定向。 - 缓冲行为使其更适合批量处理的日志场景。 示例代码: ```cpp #include <iostream> using namespace std; int main() { clog << "Logging information..." << endl; // 日志记录 return 0; } ``` --- #### 对比总结表 | 表格说明 | 流名称 | 功能描述 | 是否带缓冲 | 默认输出位置 | 是否可重定向 | |------------|------------------------------|------------------|-------------------|--------------| | `cin` | 标准输入 | —— | 键盘 | 是 | | `cout` | 标准输出 | 是 | 屏幕 | 是 | | `cerr` | 标准错误输出 | 否 | 屏幕 | 否 | | `clog` | 标准日志输出 | 是 | 屏幕 | 是 | --- #### 应用场景分析 - 当需要读取用户的实时输入时,应优先考虑 `cin`。 - 如果只是简单的打印调试信息或正常流程的结果,则可以选择 `cout`。 - 针对程序执行过程中产生的错误警告,推荐采用无缓存的 `cerr` 来即时反馈问题所在。 - 若涉及较为复杂的后台服务架构设计并希望优化资源利用率的话,那么带有缓存特性的 `clog` 将成为理想的选择之一。 ---
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值