为什么cout会立即输出?

5

cout是一个缓存流。这意味着数据将被写入缓冲区,并在流被刷新、程序终止或缓冲区完全填满时打印。

我编写了一个小程序来测试它的工作原理,但我不明白为什么它会在满足上述任何条件之前就开始打印。

#include <iostream>
#include <ctime>
using namespace std;

int main()
{
    cout << "Test";
    float secs = 5;
    clock_t delay = secs * CLOCKS_PER_SEC;
    clock_t start = clock();
    while (clock() - start < delay) { }
    return 0;
}

当运行时,“Test”会在循环开始之前输出。为什么我的输出不会缓冲,直到程序终止?

2
在打印之前尝试使用 std::ios::sync_with_stdio(false); - scohe001
1
std::ios::sync_with_stdio(false); 的确很好用,谢谢!但为什么呢? - Игорь Аникин
请查看下面的答案 - scohe001
2个回答

4

这里有一个关于此话题的讨论,可以在这里查看。

其中一个回答如下:

每个C++流都使用相关联的流缓冲区对象来执行缓冲。

当构造std::cout时,它使用与对象stdout相关联的流缓冲区,在<cstdio>中声明。 默认情况下,对std::cout的操作可以自由地与<cstdio>输出函数(如std::printf())混合使用。

实际上,同步通常意味着标准iostream对象和标准stdio对象共享缓冲区。- IS

如果在标准流的任何输入或输出操作之前调用了std::ios_base::sync_with_stdio(false),则标准C ++流将独立于标准C流运行(即它们切换到自己的单独流缓冲区)。

更多信息,请参见cppreference上的sync_with_stdio函数参考页面。

从该页面,该函数...

设置标准C ++流在每个输入/输出操作后是否与标准C流同步。

...实际上,这意味着同步的C ++流是无缓冲的,并且对于C ++流的每个I/O操作,都会立即应用于相应的C流的缓冲区。这使得可以自由地混合C++和C I/O。

但是,请注意,在进行读取或写入之后调用此函数:

如果在标准流上发生I/O后调用此函数,则其行为是实现定义的:实现范围从没有效果到销毁读取缓冲区。


2
这里还有一个很好的讨论链接。这似乎与scohe001提到的一些内容有关,但又有所不同,因此我将其放在自己的答案中。
与上面的答案相关的是该论坛上的这篇帖子,它讨论了缓冲区如何根据周围的其他代码刷新。Std::cout函数与其他流函数和常规c库函数绑定,正如scohe001所提到的那样。因此,如果调用了与其绑定的某个东西,它的缓冲区将在继续之前刷新。
您是在Linux上使用gcc编译还是在某个Windows环境中运行?来自上述论坛的这篇帖子谈到了特定于操作系统的函数,以及来自Windows的sleep()可能会导致缓冲区刷新。否则,普通的gcc编译的c++代码不会使用sleep()打印缓冲区,只要它没有遇到任何其他会在继续之前刷新缓冲区的代码。
以上这些帖子涵盖了很多信息,所以我会避免在这里复制和粘贴它们,请原谅我堆栈溢出神明。
希望这些信息能对您有所帮助!

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接