C++の std::endl とは?バッファとflushを理解する
C++で出力を書くときによく見るこのコード。
std::cout << "Hello" << std::endl;
この std::endl は単なる改行ではありません。
結論から言うと
std::endl = 改行 + バッファをflush
です。
この記事では
- バッファとは何か
-
\nとstd::endlの違い - なぜ
std::endlが遅くなるのか
を解説します。
バッファ(buffer)とは
通常、std::cout で出力するときは
std::cout << "Hello";
すぐに画面に表示されるように見えます。
しかし実際は 一度バッファに溜められます。
イメージ
std::cout
↓
[バッファ]
↓
画面
つまり
Hello
は直接画面に送られるのではなく
バッファに一時保存
されます。
なぜバッファを使うのか
理由は 高速化のためです。
もし
1文字出力するたびにOSへ書き込み
していたらとても遅くなります。
例えば
Hello
は
H
e
l
l
o
5回出力する必要があります。
そこで
バッファにまとめて保存
↓
まとめて出力
することで高速化しています。
バッファが吐き出されるタイミング
通常、次のタイミングでバッファが出力されます。
- バッファがいっぱいになったとき
- プログラムが終了したとき
-
flushが呼ばれたとき
std::endl の意味
std::endl は
std::cout << "Hello" << std::endl;
実際には
std::cout << "Hello\n";
std::cout.flush();
とほぼ同じ意味です。
つまり
改行
+
バッファを強制出力
を行います。
flushとは
flush は
バッファに溜まったデータを
今すぐ出力する
という意味です。
イメージ
バッファ
[Hello world]
↓
画面へ出力
\n と std::endl の違い
よく混乱するポイントです。
\n
std::cout << "Hello\n";
意味
改行のみ
バッファはそのまま残ります。
std::endl
std::cout << "Hello" << std::endl;
意味
改行
+
flush
つまり
今すぐ出力する
という指示になります。
std::endl が遅くなる理由
例えば次のコード。
for(int i=0;i<100000;i++){
std::cout << i << std::endl;
}
これは
100000回 flush
を行うことになります。
flush はコストが高いため
かなり遅くなる
可能性があります。
そのため通常は
std::cout << i << "\n";
を使うことが多いです。
まとめ
| 書き方 | 意味 |
|---|---|
\n |
改行のみ |
std::endl |
改行 + flush |
flush |
バッファを強制出力 |
一般的な出力では
\n を使う
必要なときだけ
std::endl
を使うのがよいでしょう。