【发布时间】:2012-06-13 22:31:33
【问题描述】:
是否有更多的输出缓冲区?如果是这样,endl 是否只刷新与cout 关联的输出缓冲区?如果只有一个缓冲区,那么是什么让cerr 和clog 这两个对象不同?
【问题讨论】:
-
这是windows-specific buffer creation function。这就像有一个用于绘图的后台缓冲区。备注部分解释了目的。
是否有更多的输出缓冲区?如果是这样,endl 是否只刷新与cout 关联的输出缓冲区?如果只有一个缓冲区,那么是什么让cerr 和clog 这两个对象不同?
【问题讨论】:
endl 刷新您将其流式传输到的任何流的输出缓冲区。例如:
cout << ... << endl; // flushes the output buffer of 'cout'
cerr << ... << endl; // flushes the output buffer of 'cerr'
ofstream file("filename");
file << ... << endl; // flushes the output buffer of 'file'
cerr 和 clog 之间的唯一区别是 clog 默认是缓冲的,而 cerr 不是。您可以使用std::unitbuf 和std::nounitbuf 操纵器为任何流打开或关闭缓冲。例如:
cerr << nounitbuf; // cerr is now buffered
clog << unitbuf; // clog is now unbuffered
注意“unitbuf”的意思是“使缓冲区大小为1”,即关闭缓冲。
【讨论】:
C(及其起源的 UNIX 环境)中的 I/O 是通过数据“流”完成的,这些数据“流”是可以读取或写入(或两者)的抽象字节序列,例如文件系统中的文件,或终端(或屏幕和键盘)等设备。
C 标准库头文件<stdio.h> 声明了一个类型FILE,用作数据流的句柄。它还声明stdin、stdout 和stderr 类型为FILE*,分别引用标准输入流、标准输出流和标准错误流。
C++ 标准库定义了 std::istream 和 std::ostream 类(统称为 iostreams),它们可用于与数据流交互(术语有点混乱,因为 C++ iostreams 类有时简称为“流”,但同一个词也表示<stdio.h>FILE`所指的抽象数据流。)
C++ 全局std::istream 对象std::cin 与标准输入流相关联(即与stdin 所指的流相同),全局std::ostream 对象std::cout 与标准输出流相关联,而全局对象std::cerr 和std::clog 是不同的对象,但都与标准错误流相关联。
cerr 和clog 之间的区别在于,默认情况下clog 使用一个流缓冲区,将写入它的字符存储在内部缓冲区中,并且仅当缓冲区填满或当缓冲区填满时才将该数据写入标准错误流显式刷新,而cerr 的streambuf 没有内部缓冲,因此所有内容都直接写入标准错误流。因为它们是单独的对象,所以它们具有单独的流缓冲区,具有不同的默认行为,但最终写入相同的标准错误流。
std::endl 可以写入任何std::ostream,因此如果您写入std::cout << std::endl,它将刷新与cout 关联的流,这通常是标准输出流。如果你写std::clog << std::endl,它将刷新与clog关联的流,这通常是标准错误流。
【讨论】:
tie()-d到cout(而且只有它,cerr和clog没有连接到它),所以阅读来自cin 的任何内容都会自动刷新cout。
sync_with_stdio 使cin 与stdin 和cout 与stdout 一致,通过使它们共享缓冲区等,但我认为答案已经足够长了!
sync_with_stdio 在程序启动时为真。