閉じる

C++の改行はstd::endlと’\n’どっち?違いと使い分け

C++で画面に出力するとき、最後に付ける改行としてstd::endl'\n'のどちらを使うべきかは、初心者が最初につまずきやすいポイントです。

本稿では両者の本質的な違い実用での使い分けを、バッファとフラッシュの基礎から丁寧に解説します。

最後まで読めば、状況に応じて迷わず選べるようになります。

C++の改行: std::endl と ‘\n’ の違い

‘\n’ は改行のみ

基本の意味

'\n'は文字リテラルで、行の終端を表すLF(Line Feed)という1文字です。

C言語でも同じ概念で、出力ストリームにこの文字が書き込まれるだけで、バッファのフラッシュは行いません

短いコード例

C++
#include <iostream>
using namespace std;

int main() {
    cout << "Hello" << '\n';   // 改行だけ。フラッシュはしない
    cout << "World" << '\n';   // 2行目
    return 0;                  // プログラム終了時にバッファはフラッシュされる
}
実行結果
Hello
World

std::endl は改行+フラッシュ

何が追加で起きるか

std::endlは操作子(manipulator)で、出力に'\n'を挿入した直後にフラッシュを行います。

したがって、毎回のstd::endlは性能コストがかかることに注意が必要です。

短いコード例

C++
#include <iostream>
using namespace std;

int main() {
    cout << "Ready..." << std::endl; // 改行して即フラッシュ。画面にすぐ出る
    cout << "Go!" << std::endl;      // これも即フラッシュ
    return 0;
}
実行結果
Ready...
Go!

非常に分かりづらいですが、実行される瞬間をよく見るとだいたい1フレームごとに出力されていると思います。

使い分けの結論: 基本は ‘\n’

先に結論

通常の改行には'\n'を使い、即時表示が必要な場面だけstd::endlを使うのが定石です。

これは不要なフラッシュを避け、無駄なシステムコールを減らすためです。

早見表

選択肢何をするか速度代表的な用途
'\n'改行のみ速い通常出力、ループ内の大量出力
std::endl改行+フラッシュ遅いプロンプト表示、ログの即時反映
std::flushフラッシュのみ改行なしで即時表示したい時

cout のバッファとフラッシュを理解する

バッファとは何か

仕組みの概要

バッファは、出力データをいったん貯めてからまとめてOSに渡すための作業領域です。

I/Oは高コストなので、まとめて出すと速いという性質を活かしています。

C++のstd::coutも内部にバッファを持つstreambufがあり、逐次書き込みを吸収します。

いつフラッシュされるか

主なトリガ

バッファは次のタイミングでフラッシュされます。

  • std::endlstd::flushstd::cout.flush()を呼んだ時
  • バッファが一杯になった時
  • プログラム終了時やstd::coutの破棄時
  • ストリームのtieにより、std::cinで入力を始める直前
  • std::unitbufが有効なストリーム(std::cerrなど)での出力時

特にstd::cinstd::coutにtieされているのが標準的初期状態です。

そのため、std::endlを使わなくても、入力前には自動的にstd::coutがフラッシュされます。

tieの挙動を確認するコード

C++
#include <iostream>
#include <string>
using namespace std;

int main() {
    // デフォルトで cin は cout に tie されている想定
    cout << "お名前を入力してください: "; // 改行もフラッシュもしていない
    string name;
    cin >> name; // cin が動く直前に cout が自動フラッシュされ、プロンプトが見える
    cout << "こんにちは, " << name << " さん!\n";
    return 0;
}
実行結果
お名前を入力してください: Taro
こんにちは, Taro さん!

std::flush との違い

endlとflushの関係

std::flushフラッシュだけを行う操作子です。

std::endl'\n'を出した後にstd::flush相当を実行します。

改行せずに即時表示したいときはstd::flushを選びます。

C++
#include <iostream>
#include <chrono>
#include <thread>
using namespace std;

int main() {
    cout << "処理中..." << std::flush; // 改行せずに即時表示
    this_thread::sleep_for(chrono::milliseconds(300));
    cout << "\r完了        \n";        // 行頭に戻して上書き、最後に改行
}
実行結果
完了

‘\n’ と改行コードの変換(Windows/Linux)

テキストモードの改行変換

'\n'はあくまでLF(0x0A)という1文字です。

ただし、テキストモードでファイルに書く場合、実装は環境に応じて改行コードを変換します。

  • Windows: ファイルではLFがCRLF(0x0D 0x0A)に変換されるのが一般的
  • LinuxやmacOS: 変換せずLFのまま

重要なのはstd::endl'\n'も、'\n'を書いた上で必要なら変換が起きるという点です。

プラットフォーム差を気にしてstd::endlを選ぶ必要はありません

使い分けの指針とコード例

高速な大量出力は ‘\n’ を使う

理由と実例

大量ループ内で毎回フラッシュすると、システムコールが頻発し極端に遅くなります。

大量出力は'\n'で改行だけに留めるのが基本です。

C++
#include <iostream>
#include <fstream>
#include <chrono>
using namespace std;

int main() {
    ofstream f1("only_newline.txt");
    ofstream f2("with_endl.txt");

    const int N = 100000; // 10万行

    // '\n' だけで書く
    auto t1 = chrono::steady_clock::now();
    for (int i = 0; i < N; ++i) {
        f1 << "line " << i << '\n'; // フラッシュしない
    }
    auto t2 = chrono::steady_clock::now();

    // std::endl で毎回フラッシュ
    auto t3 = chrono::steady_clock::now();
    for (int i = 0; i < N; ++i) {
        f2 << "line " << i << std::endl; // 毎回フラッシュで非常に遅い
    }
    auto t4 = chrono::steady_clock::now();

    auto d1 = chrono::duration_cast<chrono::milliseconds>(t2 - t1).count();
    auto d2 = chrono::duration_cast<chrono::milliseconds>(t4 - t3).count();

    cout << "newline only: " << d1 << " ms\n";
    cout << "with endl   : " << d2 << " ms\n";
}

出力例(目安、環境により変わります):

実行結果
newline only: 25 ms
with endl   : 2100 ms

入力前やログは std::endl で即時表示

プロンプトや進捗、重要ログ

ユーザの入力を促すプロンプトや、即時に見えてほしい重要ログでは確実に今すぐ表示したい場面があります。

std::endlを使うと安全です。

なお、cincoutにtieされているため、入力直前には自動フラッシュされますが、ログではtieが働かないケース(別スレッド、別ストリーム)もあり得ます。

C++
#include <iostream>
using namespace std;

int main() {
    cout << "[INFO] サーバ起動中..." << std::endl; // すぐに見せたい
    // 初期化処理...
    cout << "[INFO] 起動完了" << '\n';            // ここは即時性不要なら '\n'
}
実行結果
[INFO] サーバ起動中...
[INFO] 起動完了

明示的にフラッシュしたいときは std::flush

改行なしで即時表示

進捗バーなど、行の途中で即時反映したいときはstd::flushが便利です。

C++
#include <iostream>
#include <thread>
#include <chrono>
using namespace std;

int main() {
    for (int i = 0; i <= 100; i += 25) {
        cout << "\rProgress: " << i << "%" << std::flush; // 改行なし即時反映
        this_thread::sleep_for(chrono::milliseconds(200));
    }
    cout << "\n完了\n";
}
実行結果
Progress: 100%
完了

パイプやネットワーク出力でもフラッシュを意識

外部プロセスやストリームバッファ

他プロセスへのパイプ、ソケットに紐づいたストリームバッファなど、受け手が逐次処理するケースでは、適切なタイミングでフラッシュしないと相手側が待ち続ける可能性があります。

区切りごとにstd::flushstd::endlを挿入すると確実です。

C++
#include <iostream>
using namespace std;

int main() {
    // 行単位で読み取られる想定のパイプ出力
    cout << "HEADER v1" << std::endl;   // 先頭ヘッダは即時送る
    cout << "DATA 1" << '\n';           // まとめて送っても問題ない箇所は '\n'
    cout << "DATA 2" << '\n';
    cout << "END" << std::endl;         // 終端は確実に通知
}
実行結果
HEADER v1
DATA 1
DATA 2
END

よくある誤解と注意点

std::endl は改行の別名ではない

std::endlは改行を出すだけではなく必ずフラッシュします

別名ではなく別物である点を忘れないでください。

毎回フラッシュはパフォーマンス低下

フラッシュはOSへの書き出しを強制するため高コストです。

ループ内でのstd::endl連発は避けるべきです。

‘\n’ でも状況により自動表示される

'\n'だけでも、cin呼び出し直前のtieやプログラム終了時にはフラッシュされます。

「’\n’だと永遠に出ない」わけではないことを覚えておきましょう。

ファイル出力でも原則は同じ

ファイルでも'\n'が基本、必要箇所でstd::endlstd::flushという方針は変わりません。

WindowsとLinuxでの改行コードの差は、テキストモードの変換に任せれば十分です。

std::endl の乱用を避ける

規約として「普段は’\n’、必要時のみendl」をチーム共通のスタイルにすると、性能と可読性の両立がしやすくなります。

レビューでstd::endlの乱用を見つけたら指摘しましょう

まとめ

改行だけなら'\n'、即時に表示したい時はstd::endlというのが実戦的な結論です。

背景にはバッファとフラッシュの仕組みがあり、不要なフラッシュは性能を大きく損ないます。

入力前や重要ログ、プロトコル境界などの区切りでのみstd::endlstd::flushを使い、それ以外は'\n'を選ぶ。

このシンプルな指針を守れば、プログラムは期待通りに表示され、かつ無駄なI/Oコストを避けられます。

この記事を書いた人
エーテリア編集部
エーテリア編集部

C++をこれから学ぶ方に向けて、基礎的な文法や標準ライブラリの使い方を紹介します。モダンな書き方も初心者に合わせてやさしく説明しています。

クラウドSSLサイトシールは安心の証です。

URLをコピーしました!