C++-为什么fflush(stdout)不适用于iostream

C++ - Why fflush(stdout) does not work with iostream?

本文关键字:不适用 适用于 iostream stdout 为什么 fflush C++-      更新时间:2023-10-16

我读到了关于freopen()的文章,并意识到如果我们为其指定stdin/stdout,即使我们使用cin/cout进行编码,该函数也会工作。

经过一点研究,我发现这个链接freopen()相当于c++流,其中一个用户回答:

来自C++标准27.3.1:
"对象cin控制来自与对象stdin相关联的流缓冲区的输入,在<cstdio>中声明。">

因此,根据标准,如果我们重定向stdin,它也将重定向cincout反之亦然。

在CPPReference上也看到了类似的内容:
http://en.cppreference.com/w/cpp/io/cin
http://en.cppreference.com/w/cpp/io/cout

全局对象std::cout和std::wcout控制输出到实现定义类型的流缓冲区(从std::streambuf派生),与标准C输出流stdout关联。

这就是它有点令人困惑的地方,因为我也在读关于刷新的文章,并注意到fflush(stdout)根本无法与cin/cout一起工作。

例如,此示例代码不会打印任何内容:

#include <cstdio>
#include <iostream>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
int n;
cout << "Please, enter a number: n";
fflush(stdout);
cin >> n;
}

而下面的代码将打印到output.txt:

#include <cstdio>
#include <iostream>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
freopen("output.txt", "w", stdout);
cout << "Some string";
while (true);
}

从第一个示例代码中删除ios::sync_with_stdio(false);,它的行为与预期的一样。freopen()无论如何都能工作(不管有没有它)。

所以问题是:为什么fflush(stdout)不能与iostream一起工作,而freopen(…,stdout)可以工作?也许,这个问题会变得更深入:cin/cout与stdin/stdout的关联扩展到什么程度?

抱歉发了这么长的邮件。我尽量做到简明扼要。

我希望这是可以理解的。

提前谢谢。

附言:我特意放了ios::sync_with_stdio(false);cin.tie(0);

我的第一个问题是"你为什么要"?有一个std::ostream::flush()函数用于此目的,因此请使用例如cout.flush();

它"不起作用"的原因是用fflush(FILE* f)刷新的缓冲区与用于std::ostream的缓冲区不同(或者至少不能保证它会起作用)。std::ostream::flush()很可能确实在作为实现一部分的底层文件对象上调用了fflush(FILE*)

您在"专用"中放入的调用ios::sync_with_stdio(false)cin.tie(0)的目的是确保(1)C I/O流(stdout等)与其C++对应流(std::cout等)不同步,以及(2)确保stdoutstdin不绑定(即从stdin读取不一定会导致stdout被刷新)。

这就是为什么fflush(stdout)不会影响您的示例中的std::cout。您已经专门禁用了这种效果,这两者可能会被单独缓冲。

freopen()对任何可能与提供的文件句柄同步的C++流的影响是未定义的。在实践中,可能有一些常用的缓冲区,这解释了您所看到的情况——至少在编译器/库中是这样。但其他实现并不能保证这种行为。

相关文章: