新行字符是否也刷新缓冲区?

Cap*_*nci 7 c++ flush endl

我明白,问题,如,差异endl\n已经多次回答SO.但是他们只提到endl能够将缓冲区冲到上面stdout,而\n不是.

因此,我通过刷新缓冲区理解的是,给定的输入存储在一个缓冲区中,并且stdout仅在它遇到endl时或者一些明确的flush函数传递给它.如果是这样,我预计以下代码:

#include <iostream>
#include <unistd.h>

int main(void)
{
    std::cout << "Hello\nworld";
    sleep(2);
    std::cout << std::endl;

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

显示:

2秒后

Hello
World
Run Code Online (Sandbox Code Playgroud)

但实际产量是:

Hello
Run Code Online (Sandbox Code Playgroud)

2秒后

World
Run Code Online (Sandbox Code Playgroud)

为什么会这样?

也不\n应该存储在缓冲区中,只有在endl遇到缓冲区时才会被刷新/显示在上面stdout,但是从我观察到的\n是同样的行为endl.

Jon*_*ler 6

将评论转换为答案。

这取决于cout要去的地方。如果它到达终端(“交互式设备”),则无法完全缓冲-通常是行缓冲的,这意味着字符在换行符打印后出现,或者理论上可以不缓冲。如果要去往管道或文件或其他非交互式目标,则endl即使该流已完全缓冲,也将强制将数据输出出去,就像通常那样。

我还想知道是否既不提供换行符也不提供endlstdout一旦输出到达程序末尾,输出是否会显示在终端上,我知道stdout吗,但是它适用于所有类型的吗?

是的,当在程序的(正常)端关闭文件流时,将刷新待处理的输出。当缓冲区已满时,也会刷新它。如果程序中止,通常不会刷新待处理的输出。


Die*_*ühl 5

标准C ++流对象的默认设置(std::cinstd::coutstd::cerr,和std::clog)是它们与相应的C数据流同步的(stdinstdout,和stderr)。同步意味着对C ++和C流的交替访问会导致行为一致。例如,此代码应产生字符串hello, world

std::cout << "hel";
fprintf(stdout, "lo,");
std::cout << " wo";
fprintf(stdout, "rld");
Run Code Online (Sandbox Code Playgroud)

C ++标准没有规定如何实现此同步。一种实现方法是禁用std::cout(和系列)的任何缓冲并立即访问stdout。也就是说,以上示例可以立即将各个字符写入stdout

如果实际将字符写入stdout缓冲模式的默认设置,stdout则将使用。我在标准中找不到规范,但是通常缓冲模式的默认值stdout_IOLBF当它连接到交互式流(例如控制台)时,即在行尾刷新缓冲区。通常_IOFBF,写入文件的默认值为,即,写入完整的缓冲区后将刷新输出。结果,写入换行符std::cout可能导致刷新缓冲区。

C ++中的流通常设置为要缓冲。也就是说,向文件中写入换行符通常不会导致输出立即显示(仅当字符导致缓冲区溢出流设置为未缓冲时,才会立即显示输出)。由于stdout通常不需要同步,例如,当程序始终用于std::cout写入标准输出,但确实导致标准输出的输出显着降低时(禁用流缓冲会使它们变慢),因此可以禁用同步:

std::ios_base::sync_with_stdio(false);
Run Code Online (Sandbox Code Playgroud)

这将禁用所有流对象的同步。对于不好的实现,可能没有任何效果,而好的实现则会启用缓冲,std::cout从而导致大幅提速,并且还可能禁用行缓冲。

一旦缓冲了C ++流,就没有内置的方法可以在写入换行符时刷新它。这样做的主要原因是,处理行缓冲将需要通过流缓冲区检查每个字符,这有效地抑制了对字符的批量操作,从而导致了显着的减慢。如果需要,可以通过简单的过滤流缓冲区来实现行缓冲。例如:

class linebuf: public std::streambuf {
    std::streambuf* sbuf;
public:
    linebuf(std::streambuf* sbuf): sbuf(sbuf) {}
    int_type overflow(int_type c) {
        int rc = this->sbuf->sputc(c);
        this->sbuf->pubsync();
        return rc;
    }
    int sync() { return this->sbuf->pubsync(); }
};
// ...
int main() {
    std::ios_base::sync_with_stdio(false);
    linebuf sbuf(std::cout.rdbuf());
    std::streambuf* origcout = std::cout.rdbuf(&sbuf);

    std::cout << "line\nbuffered\n";

    std::cout.rdbuf(origcout); // needed for clean-up;
}
Run Code Online (Sandbox Code Playgroud)

tl; dr:C ++标准没有行缓冲的概念,但是当标准I / O与C的行为同步时,它可能会得到缓冲stdout