标准库使我们能忽略这些不同类型的流之间的差异,这是通过继承机制实现的。
由于不能拷贝IO对象,因此我们不能将形参或返回类型设置为流类型。进行IO操作的函数通常以引用方式传递和返回流。读写一个IO对象会改变其状态,因此传递和返回的引用不能是const的。
下图列出了IO类所定义的一些函数和标志,可以帮助我们访问和操纵流的条件状态。
管理输出缓存
每个输出流都管理一个缓冲区,用于保存程序读写的数据。如:
os<<"please enter a value:";
导致缓冲刷新(即,数据真正写到输出设备或文件)的原意有很多:
1)程序正常结束,作为main函数的return操作的一部分,缓冲刷新被执行。
2)缓冲区满时,需要刷新缓冲,而后新的数据才能继续写入缓冲区
3)我们可以使用操纵符如endl来显式刷新缓冲区
4)在每个输出操作之后,我们可以用操纵符unitbuf设置流的内部状态,来清空缓冲区。默认情况下,对cerr是设置unitbuf的,因 此写到cerr的内部都是立即刷新。
5)一个输出流可能被关联到另一个流。在这种情况下,当读写被关联的流时,关联到的缓冲区会被刷新。例如,默认情况下,cin 和cerr都关联到cout,因此读cin或cerr都会导致cout的缓冲区被刷新
我们已经使用过操纵符endl,它完成换行并刷新缓冲区的工作。IO库中含有两个类似的操纵符:frush和ends。
frush刷新缓冲区,但不输出任何额外字符
ends向缓冲区插入一个空字符,然后刷新缓冲区
如果想在每次输出操作后都刷新缓冲区,我们可以使用unitbuf操纵符。它告诉流在接下来的每次写操作之后都进行一次flush操作。而nounitbuf操纵符则重置流,使其恢复使用正常的系统管理的缓冲区刷新机制:
cout<<unitbuf; //所有输出操作后都会立即刷新缓冲区
//任何输出都立即刷新,无缓冲
cout<<nounitbuf; //回到正常的缓冲方式
当一个输入流被关联到另一个输出流时,任何试图从输入流读取数据的操作都会先刷新关联的输出流。