2017-02-24 14 views
3

私はのような質問はendl\nの間で何度も答えられていることを理解しています。しかし、endlstdoutにバッファをフラッシュすることができ、\nはバッファをフラッシュすることができます。改行文字もバッファをフラッシュしますか?

だから、私はフラッシュされ、バッファによって理解することは、入力が与えられた、ということであるバッファに格納され、それがendl、またはいくつかの明示的なflush機能渡って来るときだけstdoutに渡されます。もしそうなら、私が予想される次のコード:表示するには

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

int main(void) 
{ 
    std::cout << "Hello\nworld"; 
    sleep(2); 
    std::cout << std::endl; 

    return 0; 
} 

後2秒

Hello 
World 

しかし、実際の出力は:

Hello 

2秒後

World 

なぜですか?

\nまた、バッファに格納すべきではないとendlが発生した場合にのみ、バッファはstdout上に表示/フラッシュすることですが、私は\n観察したものからendlと同じように動作しています。

+6

それは 'cout'がどこに行くかによって決まります。それが端末( '対話型デバイス')に行くと完全にバッファリングすることはできません。通常はラインバッファーであり、改行が印刷された後に文字が現れるか、理論上はバッファリングされないことがあります。パイプやファイル、または他の非対話的なデスティネーションに向かう場合、 'endl'は、ストリームが完全にバッファされていてもデータを強制的に出力します。 –

+0

私は新しい行の文字も 'endl'も提供していないか知りたかったのですが、プログラムの終わりに達すると、出力は' stdout'に表示されますか? 'stdout'のタイプ? – CaptainDaVinci

+2

はい、ファイルストリームがプログラムの(通常の)終了時に閉じられると、保留中の出力はフラッシュされます。また、バッファがいっぱいになるとフラッシュされます。プログラムが異常終了すると、保留中の出力は通常フラッシュされません。 –

答えて

2

コメントを回答に変換します。

coutがどこに行っているかによって異なります。それが端末( '対話型デバイス')に行くと完全にバッファリングすることはできません。通常はラインバッファーであり、改行が印刷された後に文字が現れるか、理論上はバッファリングされないことがあります。パイプやファイル、または他の非対話型の宛先に行く場合は、通常はそうであるように、ストリームが完全にバッファされていても、endlはデータを強制的に出力します。

私も、私は改行文字もendlどちらを提供する場合、それはプログラムの最後に達すると、出力はstdoutに表示されます知りたいと思った、私はそれが、端末の場合と知っているが、それはに適用されますすべてのタイプのstdout

はい、ファイルストリームがプログラムの(通常の)終了時に閉じられると、保留中の出力はフラッシュされます。また、バッファがいっぱいになるとフラッシュされます。プログラムが異常終了すると、保留中の出力は通常フラッシュされません。

3

標準C++ストリームオブジェクト(std::cinstd::coutstd::cerr、及びstd::clog)のデフォルト設定は、それらが対応するCストリーム(stdinstdout、及び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の動作から同期されたとき、それはそれを得ることができます。

関連する問題