5

これが非常にばかげた質問になることはわかっていますが、「バッファ」システム全体に関する非常に多くのドキュメントを読んだ後、なぜ人々がストリームをフラッシュするのにバッファをフラッシュしないのか理解できません。

私は人々がこのようなことを書いているのを見てきました:

FILE* file=fopen("mytext.txt","wr");
char buffer[10]="";
setbuf(file,buffer);

//do some stuff....

fflush(file);
....
fclose(file);

それで、私たちは実際に何かをバッファに保存するのに、実際に何かを保存し、フラッシュする必要があるバッファを直接フラッシュするのではなく、関連するストリームをフラッシュするのはなぜだろうか.私が言ったように、それは同じことになるので、気にしないでください......)

たとえば、fflush(buffer).Why?のようなものは記述できません。

4

3 に答える 3

6

フラッシュは、ストリームの内部バッファから基になるファイルにデータをコピーします。

したがって、フラッシュ関数はコピー元とコピー先を知る必要があります。

これは I/O の実装に依存します。C++<iostream>については、Jerry Coffin の回答を参照してください。バッファ<iostream>はよりスマートです。

C-style<cstdio>では、引数を 1 つだけ指定してフラッシュする場合は、FILE*または char 配列がコピー先のファイルを認識している必要があります。

バッファはダム配列であり、読み取り/書き込み用のデータを格納するだけです。そこには追加情報がないため、バッファーへのポインターを取得する関数は、それを書き込む宛先を知ることができませfflushfflush(buffer, file);。一方、 はFILE*バッファーへのポインターを格納します (setbuf(file,buffer)関数呼び出しでポインターを設定します)。

于 2015-05-29T23:06:24.793 に答える
2

以下は、iostream とそのバッファ オブジェクトのみを扱います。C スタイルの I/O に関連するバッファについては、@milleniumbug の回答を参照してください。

ほとんどの場合、(少なくとも通常は) 基になるバッファーをフラッシュしようとして失敗した場合に、ストリームの badbit セットが必要なためです。

また、ストリームが基礎となるストリームとやり取りするときに使用する少し複雑な小さなダンスもあります。ストリームはセントリー オブジェクトを作成し、アクションを実行してから、セントリー オブジェクトを破棄します。歩哨は、接頭辞と接尾辞の操作を例外的に安全にすることを目的としています。

したがって、全体的なシーケンスは次のようになります。

create sentry
if that succeeds (sentry converts to true) call rdbuf()->pubsync()
    if that fails (returns -1) setstate(badbit);

ストリーム バッファ (たとえば、basic_filebuf) は、基になるファイル システム オブジェクトに直接接続されます。実際、iostream オブジェクトと基になるファイル オブジェクト間のすべての対話は、ファイル バッファを介して行われます。上に示したように、ストリーム オブジェクトがバッファをフラッシュする必要がある場合、バッファのpubsync()メンバ関数を呼び出してバッファ自体をフラッシュするように指示するだけです。

[参考:[ostream.unformatted]/7:

basic_ostream& フラッシュ();

効果: フォーマットされていない出力関数として動作します (27.7.3.6.1、パラグラフ 1 で説明されているように)。rdbuf() が null ポインターでない場合、sentry オブジェクトを構築します。このオブジェクトが bool 型の値に変換されたときに true を返す場合、関数は rdbuf()->pubsync() を呼び出します。その関数が -1 を返す場合、setstate(badbit) を呼び出します (ios_base::failure (27.5.5.4) をスローする可能性があります)。それ以外の場合、sentry オブジェクトが false を返すと、何もしません。

戻り値: *this.

...そして [ofstream.cons]/2:

明示的な basic_ofstream(const char* s, ios_base::openmode モード = ios_base::out);

効果: クラス basic_ofstream のオブジェクトを構築し、基本クラスを basic_ostream(&sb) で初期化し、sb を basic_filebuf() で初期化します (27.7.3.2、27.9.1.2)。次に、rdbuf()->open(s, mode|ios_base) を呼び出します。 ::アウト)。その関数がヌル ポインターを返す場合は、setstate(failbit) を呼び出します。

于 2015-05-29T23:46:04.520 に答える