8.1.3 管理输出缓冲

每个输出流都管理一个储存空间,用来保存程序读写的数据。有了缓冲机制,操作系统就可以将程序的多个输出操作组合成单一的系统级写操作。由于设备的写操作可能很耗时,允许操作系统将多个输出操作组合为单一的设备写操作可以带来性能提升。

  • 缓冲刷新即数据真正写到文件或输出设备,导致其原因为:
  1. 程序正常结束,作为main函数return操作的一部分,缓冲刷新被执行。
  2. 缓冲区满时,需要刷新缓冲,而后新的数据才能继续写入缓冲。
  3. 我们可以使用操纵符如endl来显示刷新缓冲区。
  4. 草每个输出操作之后,可以用操纵符unitbuf设置流的内部状态,来清空缓冲区。默认情况下,cerr是设置unitbuf的,因此写到cerr内容都是立即刷新的。
  5. 一个输出流可能被关联到另一个流,在这种情况下,当读写被关联的流时,关联到的流缓冲区会刷新。例如,默认情况下,cin和cerr都关联到cout,因此,读cin或写cerr都会导致cout缓冲区被刷新。
  • 刷新输出缓冲区

IO库中还有两个类似于endl的操纵符:flush和ends。flush刷新缓冲区,但不输出额外的字符,ends向缓冲区插入一个空字符,然后刷新缓冲区。

cout << "hi!" << endl; //输出hi!和一个换行,然后刷新缓冲区
cout << "hi!" << flush; //输出hi!然后刷新缓冲区,不附加任何额外字符
cout << "hi!" <<ends; //输出hi!和一个空字符,然后刷新缓冲区
  • unitbuf操纵符

unitbuf操纵符可以使我们的每次输出后都刷新缓冲区,它使流接下来的每次写操作后都进行一次flush操作。而nounitbuf操纵符则重置流,使其恢复使用正常的系统管理的缓冲区刷新机制。

cout << unitbuf; //所有输出操作后都会立刻刷新缓冲区
cout << nounitbuf; //回到正常缓冲方式

如果程序崩溃,缓冲区不会刷新。

  • 关联输入和输出流

上文序号5内容不再赘述。

tie有两个重载版本,一个不带参数,返回指向输出流的指针。如果本对象当前关联到一个输出流,则返回的就是指向这个流的指针,如果对象为关联到流,则返回空指针。另一个接受指向ostream的指针,将自己关联到此ostream。

cin.tie(&cout); //仅用于展示
ostream *old_tie = cin.tie(nullptr); //cin不再与其他流关联
cin.tie(&cerr); //cin与cerr关联
cin.tie(old_tie) //重建cin和cout的正常关联