C++ 刷新缓冲区

c++ flushing the buffer

我知道这里有很多缓冲问题,但我似乎找不到明确的答案。

std::cout << "write to screen" << std::endl;

由于 "endl",我知道此代码将写入屏幕并刷新缓冲区,但如果我这样写:

std::cout << "write to screen";

既然文本已经输出到屏幕上了,缓冲区不会被刷新吗?

std::cout << "Hello" << std::endl;

将在执行下一行代码之前写入屏幕,而

std::cout << "Hello\n";

将打印相同的内容,但在您的程序正常退出或您使用 std::cin(或您手动绑定到 std::cout 的另一个流)之前的某个时间。这意味着如果您的程序突然终止或挂在无限循环中,您可能根本看不到输出。

"Wouldn't the buffer be flushed regardless since the text has been outputted to the screen?"

没有! std::endl 表示冲洗。底层缓冲区不会被刷新(写在屏幕上), 直到达到某个 watermark(缓冲区大小)。

如果你想刷新它,请明确调用cout.flush()

std::cout << "write to screen";
std::cout.flush();

解决方案的真正关键在于,底层 std::basic_streambuf 接口实际实现了什么。
可能有多种实现方式:

  1. 每次命中底层缓冲区的某个水印时调用flush()
  2. 每次都调用flush()(效率不是很高)
  3. 在打印 '\n' 后立即调用 flush()
  4. 调用 flush() std::endl

内部缓冲区管理不应该是您关心的事情,除非您试图提供自己的 std::basic_streambuf 实现。

Wouldn't the buffer be flushed regardless since the text has been outputted to the screen?

假设您已经看到输出到屏幕的文本,那么,缓冲区已被刷新。

我认为混淆是关于这一行的:

std::cout << "write to screen";

没有 std::endl 并不代表 "don't flush the buffer"。它只是意味着 "I'm not saying when to flush the buffer"。

有多种方法可以确保您的 std::ostream 被冲洗:

  1. 手动 std::endl, std::flush, or a direct call to ostream::flush()
  2. 取决于绑定到您的 ostream 的稍后使用的输入流:std::basic_ios::tie()
  3. 取决于与 C 流的关联:std::ios_base::sync_with_stdio

    这意味着任何会刷新相应 C 流的东西也会刷新 C++ 流,例如调用 fflush() 或(可能自动)选择的缓冲策略。
    像行缓冲。

    来自 C11 草稿:

    7.21.3 Files

    3 When a stream is unbuffered, characters are intended to appear from the source or at the destination as soon as possible. Otherwise characters may be accumulated and transmitted to or from the host environment as a block. When a stream is fully buffered, characters are intended to be transmitted to or from the host environment as a block when a buffer is filled. When a stream is line buffered, characters are intended to be transmitted to or from the host environment as a block when a new-line character is encountered. Furthermore, characters are intended to be transmitted as a block to the host environment when a buffer is filled, when input is requested on an unbuffered stream, or when input is requested on a line buffered stream that requires the transmission of characters from the host environment. Support for these characteristics is implementation-defined, and may be affected via the setbuf and setvbuf functions.
    7 At program startup, three text streams are predefined and need not be opened explicitly — standard input (for reading conventional input), standard output (for writing conventional output), and standard error (for writing diagnostic output). As initially opened, the standard error stream is not fully buffered; the standard input and standard output streams are fully buffered if and only if the stream can be determined not to refer to an interactive device.

  4. 正在等待内部缓冲区溢出。

现在,作为一般准则:不要手动刷新流,这样做会显着降低性能。当然,除非它是正确性所必需的。