web-dev-qa-db-ja.com

std :: coutはバッファリングされていますか?

「スコット・マイヤーズ」の古くて興味深い記事を読んでいるだけです

http://aristeia.com/Papers/C++ReportColumns/novdec95.pdf

基本的には、'\n'よりもstd::endlを使用することを好むことです(私はこれに同意し、何年も同じ拡張を使用しています)。

[〜#〜] but [〜#〜]最後のセクションは、2つの理由で全体が無意味になったため、これが彼の本に含まれていなかったことを示していますポイント:

  1. std::coutはバッファリングされませんでした。
  2. Std :: coutのios::unitbufの状態は明示的に定義されていません(したがって、実装に依存します)。

簡単に調べましたが、1の明示的な標準参照が真であることがわかりませんでした。 std::coutは、私がいつも理解していることに反して、バッファリングされていませんか?

20
Martin York

はい、バッファリングされています:

C++ 11 27.4.2 [narrow.stream.objects]/3:オブジェクトcoutは、オブジェクトstdoutに関連付けられたストリームバッファへの出力を制御します

この記事は、C++ 98標準になった1995年のドラフトバージョンに言及しています。それが何か違うことを言っているのかどうかはわかりません。

ポイント2に関しては、unitbufcerrを除いて、すべてのストリーム(basic_iosコンストラクターの事後条件で指定)でwcerrは最初はfalseです。それ以外の場合は明示的に指定します。繰り返しますが、それは参照されている古代のドラフトではかなり異なるかもしれません。

18
Mike Seymour

まず、_std::cout_(または_std::cerr_)をバッファリング解除する必要はありません。唯一の要件は、_std::cerr_に_std::basic_ios::unitbuf_が設定されていることです(各出力関数の最後にフラッシュされるように:_<<_またはフォーマットされていない出力関数)。一方、std::basic_ios::sync_with_stdio(false)を呼び出さない限り、C++ストリームへの出力と対応するCストリームへの出力(つまり、_std::cout_とstdout)は同じ効果を持つ必要があります。理論的には、これはいくつかの方法で実行できます。stdout関数は_std::cout_の関数に転送でき、_std::cout_出力はstdoutに転送できます。または、内部でいくつかの共通のバッファー実装を共有できます。実際には、事実上すべての実装で_std::cout_がstdoutに転送されます。

Cは、stderrが完全にバッファリングされないこと、およびstdoutが完全にバッファリングされる可能性があるのは、対話型デバイスを参照しないと判断できる場合のみであることを指定します(実装によって定義された「対話型デバイス」の意味)。通常、stdoutはラインバッファリングされ(iostreamには存在しない概念)、stderrはバッファリングされませんが、C標準では保証されません(今日は当てはまらない可能性があります。最後に実際に調べたのは20を超えていました数年前)。とにかく、stdoutに転送するだけの実装は、転送先のC実装のルールに従い、_std::cout_とstdoutへの出力が正しい順序で出力されるようにするためにいくつかの手順を実行する必要はありません。 、およびそのstdoutは、Cの規則に従っているかのように動作します。

パフォーマンスが心配な場合は、いくつかのトライアルを実行することをお勧めします。自分で開いた_std::ofstream_に出力するのにかかる時間と、_std::cout_に出力するのにかかる時間(_sync_with_stdio_を呼び出した場合と呼び出さない場合の両方)を測定してみてください。出力がリダイレクトされました。違いは興味深いはずです。

10
James Kanze

C++標準では、すべての入力と出力が、すべての読み取りと書き込みが最終的にCストリームの読み取りと書き込みによって行われたかのように定義されています([iostream.objects.overview])。

ヘッダーは、(27.9.2)で宣言された関数によって提供される標準Cストリームにオブジェクトを関連付けるオブジェクトを宣言し、これらのオブジェクトを使用するために必要なすべてのヘッダーを含みます。

これらのオブジェクトにアタッチされた標準Cストリームの動作については、C標準(§7.19.3)を参照する必要があります。

プログラムの起動時に、3つのテキストストリームが事前定義されており、明示的に開く必要はありません。標準入力(従来の入力を読み取るため)、標準出力(従来の出力を書き込むため)、および標準エラー(診断出力を書き込むため)です。最初に開いたとき、標準エラーストリームは完全にはバッファリングされていません。標準入力ストリームと標準出力ストリームは、ストリームが対話型デバイスを参照していないと判断できる場合にのみ、完全にバッファリングされます。

ここではC99標準から引用していますが、(セクション番号のモジュロ変更)C標準のすべてのバージョンで同じであると合理的に確信しています。

9
Jerry Coffin

このページによると--- http://www.programmingincpp.com/flush-the-output-stream-buffer.html -std :: coutはバッファリングされています。 cout << ...ステートメントの後、フラッシュされる前にプログラムクラッシュが発生したため、印刷に失敗しました。

cout << "My error or flag message, but it's not flushed, so I never see it";

//system crash!

cout << endl;
2

私がフォーム here を読んだところ、coutは通常バッファリングされていますが、コンソールなどのインタラクティブな環境に出力されることを検出すると、バッファリングされていない状態にフォールバックします。

したがって、出力をリダイレクトすると(UNIXでは「>」を使用)、バッファリングされた動作が開始されます。

リンクされた投稿で詳細をご覧ください。

2
Alex