標準C++ストリームオブジェクト(std::cin
、std::cout
、std::cerr
、及びstd::clog
)のデフォルト設定は、それらが対応するCストリーム(stdin
、stdout
、及びstderr
)と同期していることです。同期化とは、C++ストリームとCストリームの交互アクセスにより、一貫した動作が行われることを意味します。C++標準では、この同期の実装方法には何の義務を負いません
std::cout << "hel";
fprintf(stdout, "lo,");
std::cout << " wo";
fprintf(stdout, "rld");
:たとえば、次のコードは、文字列hello, world
を生成することが期待されます。これを実装する1つの方法は、std::cout
(およびファミリ)のバッファリングをすべて無効にしてすぐにstdout
にアクセスすることです。つまり、上記の例では、すぐに個々の文字をstdout
に書き込むことができます。
実際に文字がstdout
に書き込まれている場合、バッファリングモードのデフォルト設定はstdout
になります。標準で仕様を見つけることはできませんが、通常、バッファリングモードのデフォルト値はstdout
で、対話型ストリーム(コンソールなど)に接続されている場合は_IOLBF
、つまりバッファが行末でフラッシュされます。ファイルへの書き込みのデフォルトは、通常、_IOFBF
であり、すなわち、完全なバッファが書き込まれると出力がフラッシュされる。その結果、改行をstd::cout
に書き込むと、バッファがフラッシュされる可能性があります。
C++のストリームは、通常、バッファリングされるように設定されています。つまり、改行をファイルに書き込むと、出力がすぐに表示されることはありません(文字がバッファのオーバーフローを引き起こした場合にはすぐに表示され、ストリームはバッファなしに設定されます)。 stdout
との同期は、多くの場合、プログラムが常にstd::cout
を使用して標準出力に書き込む場合など、標準出力への出力が非常に劇的に遅くなる場合があります(ストリームのバッファリングを無効にすると、が遅くなります)
std::ios_base::sync_with_stdio(false);
これにより、すべてのストリームオブジェクトの同期が無効になります。悪い実装では効果がないかもしれませんが、良い実装ではstd::cout
のバッファリングが有効になり、大幅なスピードアップとなり、おそらくラインバッファリングも無効になります。
C++ストリームがバッファされると、改行が書き込まれたときにフラッシュされる組み込みの方法はありません。これの主な理由は、ラインバッファリングを処理するには、ストリームバッファによる各文字の検査が必要となり、文字の一括操作が効果的に抑制され、それにより大幅なスローダウンが生じるからです。必要に応じて、単純なフィルタリングストリームバッファを使用してラインバッファリングを実装できます。たとえば、次のように
class linebuf: public std::streambuf {
std::streambuf* sbuf;
public:
linebuf(std::streambuf* sbuf): sbuf(sbuf) {}
int_type overflow(int_type c) {
int rc = this->sbuf->sputc(c);
this->sbuf->pubsync();
return rc;
}
int sync() { return this->sbuf->pubsync(); }
};
// ...
int main() {
std::ios_base::sync_with_stdio(false);
linebuf sbuf(std::cout.rdbuf());
std::streambuf* origcout = std::cout.rdbuf(&sbuf);
std::cout << "line\nbuffered\n";
std::cout.rdbuf(origcout); // needed for clean-up;
}
TL; DR:C++標準では、ラインバッファリングの概念がありませんが、標準I/Oがstdout
のCの動作から同期されたとき、それはそれを得ることができます。
それは 'cout'がどこに行くかによって決まります。それが端末( '対話型デバイス')に行くと完全にバッファリングすることはできません。通常はラインバッファーであり、改行が印刷された後に文字が現れるか、理論上はバッファリングされないことがあります。パイプやファイル、または他の非対話的なデスティネーションに向かう場合、 'endl'は、ストリームが完全にバッファされていてもデータを強制的に出力します。 –
私は新しい行の文字も 'endl'も提供していないか知りたかったのですが、プログラムの終わりに達すると、出力は' stdout'に表示されますか? 'stdout'のタイプ? – CaptainDaVinci
はい、ファイルストリームがプログラムの(通常の)終了時に閉じられると、保留中の出力はフラッシュされます。また、バッファがいっぱいになるとフラッシュされます。プログラムが異常終了すると、保留中の出力は通常フラッシュされません。 –