据我所知,默认情况下,C ++支持的所有流IO都是缓冲的。
这意味着要输出的数据被放入缓冲区直到它已满,然后被发送到输出设备,类似于输入,一旦缓冲区为空,就会读取数据...所有这一切都是这样做的可以最大限度地减少昂贵的系统调用。
但是如何在行动中验证这种行为。我的意思是考虑以下代码
int main()
{
cout << "Hello world\n";
return 0
}
这里的缓冲在哪里?我知道有缓冲发生,但如何解释呢?屏幕上会立即显示输出,那么实际看到实际缓冲I / O的代码示例是什么?
答案 0 :(得分:8)
首先,并非所有iostream都被缓冲;缓冲由附件处理
streambuf
。在filebuf
的情况下(由ifstream
和ofstream
使用
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
因为立即打印了无缓冲的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;
}