C ++缓冲流IO

时间:2012-07-09 09:40:11

标签: c++ iostream buffered

据我所知,默认情况下,C ++支持的所有流IO都是缓冲的。

这意味着要输出的数据被放入缓冲区直到它已满,然后被发送到输出设备,类似于输入,一旦缓冲区为空,就会读取数据...所有这一切都是这样做的可以最大限度地减少昂贵的系统调用。

但是如何在行动中验证这种行为。我的意思是考虑以下代码

int main()
{
    cout << "Hello world\n";
    return 0
}

这里的缓冲在哪里?我知道有缓冲发生,但如何解释呢?屏幕上会立即显示输出,那么实际看到实际缓冲I / O的代码示例是什么?

3 个答案:

答案 0 :(得分:8)

首先,并非所有iostream都被缓冲;缓冲由附件处理 streambuf。在filebuf的情况下(由ifstreamofstream使用 cout),输入将尽可能多地读取,最大为 缓冲区和输出将在溢出时刷新缓冲区 显式刷新或关闭,或者当对象被破坏时(哪个 隐式调用close)。

flush的情况有点特殊,因为它永远不会被破坏 关闭。系统保证exit将是。{1}} 调用main后至少调用一次(这就是发生的事情 当你从cout返回时。这意味着之前的任何输出 从主要归来将被冲洗;如果您正在使用tie 静态对象的析构函数,你仍然需要一个显式的flush 当然。

也可以cout输出流的输出流; cin 默认情况下与std::endl绑定。在这种情况下,任何输入的尝试 绑定的流将刷新输出。

通常的惯例是使用'\n'而不是简单地使用std::endl 输出'\n'; unitbuf输出<<,然后刷新 流。对于要显示所有输出非常重要的流 及时,有一个std::cerr标志可以设置,这意味着 流将在每个sleep(10)运算符的末尾刷新。 (sleep默认设置此项。)

最后,如果你想看到缓冲效果,可以选择类似的东西 输出后{{1}}。如果输出立即显示,则表示已经输出 酡;如果它没有被缓冲,则发生冲洗 隐含地在{{1}}之后。

答案 1 :(得分:4)

请尝试以下代码:

int main()
{
    for( int i =0 ; i < 10; i ++ )
    {
        cout << i << " ";
        cerr << i << " ";
    }
}

缓冲输出通常是在流对象被销毁的情况下刷新的,所以上面的代码会打印出来(并不总是打印出来,但是gcc 4.6.3对我来说是这样的)

0 1 2 3..9
0 1 2 3..9

而不是

0 0 1 1 2 2 3 3 .... 9 9 

my output

因为立即打印了无缓冲的cerr(第一个序列),并且在cout的末尾打印了缓冲的main()

答案 2 :(得分:4)

尝试以下程序。 sleep(1)用于引入延迟(1秒),我正在使用linux,因此sleep适用于我。如果您无法使其工作,请尝试其他方法来延迟此程序(例如,简单的for循环)。如果您没有看到任何缓冲效果,也可以尝试增加缓冲区大小(取消注释注释的代码行)。

在我的操作系统(Linux 3.2.0)和编译器(g++ 4.6.3)上,此程序打印“Portion1Portion2”,然后打印“Portion3Portion4”,然后打印“Portion5”。 std :: endl guaranteed to flush缓冲区,但正如您所看到的,换行符也适用于我。

#include <iostream>
#include <unistd.h>

using namespace std;

int main () {
    // Try uncommenting following lines to increase buffer size
    // char mybuf[1024];
    // cout.rdbuf()->pubsetbuf(mybuf, 1024);

    cout << "Portion1";
    sleep(1);
    cout << "Portion2\n";
    sleep(1);
    cout << "Portion3";
    sleep(1);
    cout << "Portion4" << endl;
    sleep(1);
    cout << "Portion5" << endl;
    sleep(1);
    cout << "Done!" << endl;

    return 0;
}