我明白,问题,如,差异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.
将评论转换为答案。
这取决于cout要去的地方。如果它到达终端(“交互式设备”),则无法完全缓冲-通常是行缓冲的,这意味着字符在换行符打印后出现,或者理论上可以不缓冲。如果要去往管道或文件或其他非交互式目标,则endl即使该流已完全缓冲,也将强制将数据输出出去,就像通常那样。
我还想知道是否既不提供换行符也不提供
endl,stdout一旦输出到达程序末尾,输出是否会显示在终端上,我知道stdout吗,但是它适用于所有类型的吗?
是的,当在程序的(正常)端关闭文件流时,将刷新待处理的输出。当缓冲区已满时,也会刷新它。如果程序中止,通常不会刷新待处理的输出。
标准C ++流对象的默认设置(std::cin,std::cout,std::cerr,和std::clog)是它们与相应的C数据流同步的(stdin,stdout,和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。