C ++ - 为什么fflush(stdout)不能与iostream一起使用?

时间:2017-01-21 06:46:19

标签: c++ iostream stdio fflush

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

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

  

来自C ++标准27.3.1:
  &#34;对象cin控制与stdin中声明的对象<cstdio>关联的流缓冲区的输入。&#34;
  
  因此,根据标准,如果我们重定向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输出流标准输出相关联。

那里有点令人困惑,因为我也在阅读有关冲洗的内容,并注意到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 个答案:

答案 0 :(得分:4)

您“故意”放置的调用ios::sync_with_stdio(false)cin.tie(0)的目的是确保(1)CI / O流(stdout等)不是与他们的C ++对应物(std::cout等)和(2)同步以确保stdoutstdin没有绑定(即从stdin读取不一定导致{{ 1}}被刷新)。

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

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

答案 1 :(得分:3)

我的第一个问题是“你为什么要”?为此目的有一个std::ostream::flush()功能,所以请使用它,例如cout.flush();

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