Home Articles

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

Asked
Viewed 169 times
2

我正在阅读 freopen() ,并意识到如果我们指定stdin / stdout,即使我们使用cin / cout进行编码,该函数也能正常工作 .

研究了一下,我发现了这个链接freopen() equivalent for c++ streams,其中一个用户回答:

来自C标准27.3.1:“对象cin控制与对象stdin关联的流缓冲区的输入,在<cstdio>中声明 . ”所以根据标准,如果我们重定向stdin它也将重定向cin . cout反之亦然 .

在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)有效?也许,这个问题可以更深入:与stdin / stdout相关的cin / cout扩展名是什么?

对不起,很长的帖子 . 我试着尽可能详细和简洁 .

我希望这是可以理解的 .

提前致谢 .

P.S . :我故意把 ios::sync_with_stdio(false);cin.tie(0); .

2 Answers

  • 4

    我的第一个问题是"why would you want to"?为此目的有一个std::ostream::flush()函数,所以请使用它 . cout.flush(); .

    它的原因是"doesn't work"是用 fflush(FILE* f) 刷新的缓冲区与用于 std::ostream 的缓冲区不同(或者至少它's not guaranteed that it will be). It'很可能 std::ostream::flush() 确实在作为实现的一部分的底层文件对象上调用了 fflush(FILE*) .

  • 3

    您在"on purpose"中调用 ios::sync_with_stdio(false)cin.tie(0) 的目的是确保(1)CI / O流( stdout 等)与其C对应物( std::cout 等)和(2)不同步以确保 stdout 并且 stdin 没有绑定(即从 stdin 读取并不一定会导致 stdout 被刷新) .

    这就是 fflush(stdout) 在您的示例中不影响 std::cout 的原因 . 您已经专门禁用了这样的效果,并且两者可以单独缓冲 .

    freopen() 对可能与提供的文件句柄同步的任何C流的影响未定义 . 在实践中,可能会有一些共同使用的缓冲区,这解释了您所看到的 - 至少,使用您的编译器/库 . 但是其他实现无法保证这种行为 .

Related