C++ 输出缓冲区的管理
2015-08-17 23:13
429 查看
在C++中,每个I/O对象管理一个缓冲区,用于存储程序读写的数据。本文将对输出缓冲区的管理进行简单的讲解。
举一个简单的例子:
系统将字符串字面值存储在与流
(1) 程序正常结束。作为
注意:
如果程序不正常结束,输出缓冲区将不会刷新。在尝试调试已经崩溃的程序时,通常会根据最后的输出找出程序发生错误的区域。如果崩溃出现在某个特定的输出语句后面,则可能是在程序的这个位置之后出错。
(2) 在一些不确定的时候,缓冲区可能已经满了,在这种情况下,缓冲区将会在写下一个值前刷新;
(3) 使用操作符显示地刷新缓冲区,例如行结束符
注意:
a)
b) 如果仅因为缓冲区没有刷新,程序员将浪费大量时间跟踪调试并没有执行的代码。基于这个原因,输出时应更多使用
c) 除了
(4) 在每次输出操作完成后,使用
注意: 如果需要刷新所有输出,最好使用
其中,
(5) 可将输出流与输入流关联
注意:
a)
一个
b) 交互式系统通常应确保它们的输入和输出流是捆绑在一起的。这样做意味着可以保证任何输入,包括给用户的提示,都在试图读之前输出。
参考文献:《C++ Primer中文版(第四版)》,Stanley B. Lippman 等著。
举一个简单的例子:
myOs << "Please enter a value: ";
系统将字符串字面值存储在与流
myOs关联的缓冲区中。(至于什么是流、缓冲区,可以阅读:C++ Primer Plus(Fifth Edition), Stephen Prata一书中的介绍)。下面几种情况将导致缓冲区的内容被刷新,即写入到真实的输出设备或者文件:
(1) 程序正常结束。作为
main()返回工作的一部分,将清空所有输出缓存区;
注意:
如果程序不正常结束,输出缓冲区将不会刷新。在尝试调试已经崩溃的程序时,通常会根据最后的输出找出程序发生错误的区域。如果崩溃出现在某个特定的输出语句后面,则可能是在程序的这个位置之后出错。
(2) 在一些不确定的时候,缓冲区可能已经满了,在这种情况下,缓冲区将会在写下一个值前刷新;
(3) 使用操作符显示地刷新缓冲区,例如行结束符
std::endl;
注意:
a)
std::endl操作符的作用有两个:输出一个换行符并刷新缓冲区。而C中经常使用的换行符
\n,并不具备刷新缓冲区的作用。
b) 如果仅因为缓冲区没有刷新,程序员将浪费大量时间跟踪调试并没有执行的代码。基于这个原因,输出时应更多使用
std::endl而非
\n,使用
std::endl则不必担心程序崩溃时输出是否悬而未决(即还留在缓冲区,未输出到设备中)。
c) 除了
std::endl操作符外,C++还提供了另外两种操作符:
std::flush和
std::ends,前者用于刷新流,但不会在输出中添加任何字符,后者比较少用到,会在缓冲区中插入空字符
null然后刷新。
std::cout << "Hello world!" << std::flush; // flushes the buffer; adds no data std::cout << "Hello world!" << std::ends; // inserts a null, then flushes the buffer std::cout << "Hello world!" << std::endl; // inserts a newline, then flushes the buffer
(4) 在每次输出操作完成后,使用
unitbuf操作符设置流的内部状态,从而清空缓冲区;
注意: 如果需要刷新所有输出,最好使用
unitbuf操作符。这个操作符会在每次执行完流输出时刷新流,并且不会在输出中添加任何字符:
std::cout << std::unitbuf << "first" << "second" << std::nounitbuf; // equal to the follow: std::cout << "first" << std::flush << "second" << std::flush;
其中,
std::nounitbuf是结束
std::unitbuf的作用,使输出流恢复到正常的、由系统管理的缓冲区刷新方式。
(5) 可将输出流与输入流关联
tie起来。在这种情况下,任何读输入流的尝试都将首先刷新其输出流关联的缓冲区。而标准库中提供了将
std::cout和
std::cin绑在一起的方法:
tie。
注意:
a)
tie函数可用
istream(例如:
ifstream)或
ostream(例如:
ofstream)对象调用,使用一个指向
ostream对象的指针形参。调用
tie函数时,将实参流绑在调用该函数的对象上。如果一个流调用
tie函数将其本身绑在传递给
tie的
ostream实参对象上,则该流上的任何I/O操作都会刷新实参所关联的缓冲区:
/* the library ties std::cin and std::cout */ std::cin.tie( &std::cout ); ostream *old_tie = std::cin.tie(); /* break tie to std::cout, std::cout no longer flushed when std::cin is read */ std::cin.tie( 0 ); /* restablish normal tie between std::cin and std::cout */ std::cin.tie( old_tie );
一个
ostream对象每次只能与一个
istream对象绑在一起。如果在调用
tie函数时传递实参0,则打破该流上已存在的捆绑。
b) 交互式系统通常应确保它们的输入和输出流是捆绑在一起的。这样做意味着可以保证任何输入,包括给用户的提示,都在试图读之前输出。
参考文献:《C++ Primer中文版(第四版)》,Stanley B. Lippman 等著。
相关文章推荐
- C++ 输出缓冲区的管理
- 逆波兰表达式实现计算器(附c++代码)
- C++中变量的作用域与生命周期
- C++拷贝构造函数详解
- c++类的初创建(复数类)
- C++对象模型——临时性对象 (第六章)
- C++类静态成员与类静态成员函数
- C++学习:任意合法状态下汉诺塔的移动
- 2048小游戏c++实现
- 利用opencv源码和vs编程序训练分类器haartraining.cpp
- 最小生成树普利姆算法c语言实现__Prim
- C++读写.mat文件
- C++学习:任意合法状态下汉诺塔的移动(原创)
- C++ 虚函数表解析
- Example of MPI_Type_struct
- 二分查找递归和非递归
- C++_编写动态链接库
- 二分查找的C++非递归实现
- 关于汇编指令:NEG 用C\C++如何操作的问题
- 关于汇编指令:NEG 用C\C++如何操作的问题