C ++:「std :: endl」vs「\ n」


569

多くのC ++の本には、このようなサンプルコードが含まれています...

std::cout << "Test line" << std::endl;

...だから私もいつもそうしている。しかし、代わりに次のような作業中の開発者からの多くのコードを見てきました。

std::cout << "Test line\n";

どちらかを優先する技術的な理由はありますか、それともコーディングスタイルの問題ですか?




25
@derobertこれはもう一方より古い
Kira

3
@HediNaily確かにそうです。しかし、もう一方の答えの方がやや良い印象を与えたので、そのようにすることにしました。また、もう1つはやや広めで、もカバーしてい'\n'ます。
derobert 2013年

stackoverflow.com/a/30968225/3163618では、パフォーマンスが大幅に異なる場合があります。
qwr

回答:


473

ファイルがテキストモードで開いていると仮定すると、さまざまな行末文字は関係ありません。これは、バイナリを要求しない限り得られるものです。コンパイルされたプログラムは、コンパイルされたシステムに適切なものを書き出します。

唯一の違いはstd::endl、出力バッファーをフラッシュすることとフラッシュ'\n'しないことです。バッファを頻繁にフラッシュしたくない場合は、を使用してください'\n'。実行する場合(たとえば、すべての出力を取得する必要があり、プログラムが不安定な場合)は、を使用しますstd::endl


24
または、バッファリングされておらず、すべての出力操作でフラッシュされるため、の::std::cerr代わりに使用することを検討してください::std::cout
10

142
@Omnifarious:いいえstd :: cerrはエラー用に予約する必要があります。2つのストリームは一緒に同期されないため、coutにテキストを出力すると、バッファリングされ、cerrが出力に直接移動するため、混合モードの表示になります。想定されているもの(エラー)にはcerrを、意図されているもの(通常の対話)にはcoutを使用します。
マーティンヨーク

23
@Lucas:プラットフォームを認識するのは '\ n'だけです。
CBベイリー

32
@LokiAstari:stderr「エラー」用だとは言えません。むしろ、可能であれば、帯域外の診断メッセージ用です。./prog > file真のプログラムペイロードのみを言って保存することは可能ですが、プログラムは通常の対話であっても、より多くのステータス情報を出力したい場合があります。
Kerrek SB、2011

13
「多くの実装では、標準出力はラインバッファリングされます。std:: cout.sync_with_stdio(false)が実行されない限り、「\ n」を書き込むとフラッシュが発生します。」ここからコピー
GuLearn 2013

249

違いは次のように説明できます。

std::cout << std::endl;

に相当

std::cout << '\n' << std::flush;

そう、

  • std::endl出力をすぐにフラッシュしたい場合に使用します。
  • \nパフォーマンスが心配な場合に使用します(<<演算子を使用している場合はおそらくそうではありません)。

\nほとんどの回線で使用しています。
次にstd::endl、段落の最後で使用します(ただし、これは単なる習慣であり、通常は必要ありません)。

他の主張とは逆に\n、ストリームがファイルに送られる場合(std::cinそしてstd::cout特別であるがファイル(またはファイルのような)である場合)にのみ、文字は正しいプラットフォームの行末シーケンスにマップされます。


5
多くの場合、「出力をすぐに見る」coutはに関連していますcin。つまり、から入力を読み取った場合cincout最初にフラッシュされるためです。しかし、から読み取らずにプログレスバーなどを表示したい場合cinは、フラッシュが便利です。
Chris Jester-Young、

9
@LokiAstari:<<演算子を使用している場合は、おそらくパフォーマンスについて心配していません -なぜですか?operator<<パフォーマンスが良くないこと、またはパフォーマンスに使用する代替手段がわからないことを知りませんでしたか?これをさらに理解するために私にいくつかの資料を指摘してください。
legends2k 2014年

8
@ legends2k:C ++ストリームはCのprintf()ほどパフォーマンスが良くないという古い妻の話があります。ある程度までは本当ですが、速度の主な違いは、C ++ストリームを誤って使用している人が原因です。stackoverflow.com/a/1042121/14065 C ++では、iostreamとC-streamの同期を解除しsync_with_stdio(false)、出力を継続的にフラッシュしないでください。いつそれを行うべきかライブラリーに考えさせます。stackoverflow.com/a/1926432/14065
マーティンヨーク

6
@Loki:sync_with_stdioiostreamをstdioと同じくらい高速にする都市伝説があります。 そうではありません
ベンフォイト

2
@BenVoigt:私は上記の言い回しに注意しました(そのため、満足しています)。stdioほどパフォーマンスは良くありません(より多くのことを行うため)。しかし、人々が不満を言うパフォーマンスのギャップの多くは、stdioとの同期が原因です。
マーティンヨーク


30

あなたが使うつもりならそこに暗黙の別の関数呼び出しがあります std::endl

a) std::cout << "Hello\n";
b) std::cout << "Hello" << std::endl;

a)オペレーターを<<1回呼び出す。
b)オペレーターを<<2回呼び出す。


19
明らかかもしれませんが、スレッド化されたプログラムに大きな影響を与えます。通常、最初のバージョンは1行で1行を書き込み、2番目のバージョンは他のスレッドからの書き込みによって分割される可能性があります。多くの場合、これを回避するために自分でstd :: cout << "hello \ n" << std :: flushと書いています。
smparkes

どうstd::cout << "Hello" << "\n";ですか?
byxor 2018

1
@byxor他の回答で説明されているように、バッファのフラッシュ以外はほとんど同じです。とにかく、2つの文字列リテラルを1つにマージできる場合は冗長です。
iBug 2018

さて、出力される文字列がリテラルではない場合、への呼び出し<<はケースaでも2になるため、1つまたは2つ<<(または一般的に2つの関数呼び出し)の必要性を要求しません。違い\nendl
Enrico Maria De Angelis

笑い、それが私が\ nを使う理由ではありません。
カルロウッド

28

私はこれについて標準で読んだことを思い出したので、ここに行きます:

C ++プログラムがCRTとインターフェースするため、標準ストリームの動作を定義するC11標準を参照してください。C11標準は、ここでフラッシュポリシーを管理する必要があります。

ISO / IEC 9899:201x

7.21.3§7

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

7.21.3§3

ストリームがバッファリングされていない場合、文字はソースから、または宛先にできるだけ早く表示されるようになっています。そうしないと、文字が蓄積され、ホスト環境との間でブロックとして送信されます。ストリームが完全にバッファリングされている場合、文字は、バッファがいっぱいになったときにブロックとしてホスト環境との間で送受信されることを目的としています。ストリームがラインバッファリングされている場合、改行文字が検出されると、文字はホスト環境との間でブロックとして転送されるように意図されています。さらに、バッファがいっぱいになったとき、バッファリングされていないストリームで入力が要求されたとき、またはホスト環境からの文字の送信を必要とするラインバッファリングストリームで入力が要求されたときに、文字はブロックとしてホスト環境に送信されるように意図されています。 。

これは、非対話型デバイスを参照している場合に限り、完全にバッファリングされることstd::coutを意味します。つまり、端末にstdoutが接続されている場合、動作に違いはありません。std::cin

ただし、std::cout.sync_with_stdio(false)が呼び出された場合、'\n'インタラクティブデバイスに対してもフラッシュは発生しません。それ以外の場合'\n'std::endl、ファイルへのパイプを行わない場合と同等です:c ++ ref on std :: endl


19

どちらも適切な行末文字を書き込みます。それに加えて、endlはバッファをコミットさせます。不要なコミットはパフォーマンスに影響を与える可能性があるため、ファイルI / Oを実行するときにendlを使用することは通常ありません。



10

Qtとを使用するとendl、誤って誤ったendl値を使用してしまい、非常に驚​​くべき結果をもたらす可能性があります。次のコードスニペットを参照してください。

#include <iostream>
#include <QtCore/QtCore> 
#include <QtGui/QtGui>

// notice that there is no "using namespace std;"
int main(int argc, char** argv)
{
    QApplication qapp(argc,argv);
    QMainWindow mw;
    mw.show();
    std::cout << "Finished Execution!" << endl;
    // This prints something similar to: "Finished Execution!67006AB4"
    return qapp.exec();
}

(これは正しかったでしょう)のendl代わりに私が書いたことに注意してください、std::endlそして明らかendlqtextstream.hで定義された関数があります(これはQtCoreの一部です)で。

名前空間の潜在的な問題"\n"endl完全に回避する代わりに使用する。これは、シンボルをグローバル名前空間に配置すること(Qtがデフォルトで行うように)が悪い考えである良い例でもあります。


31
ああ!誰になりたいですusing namespace std;か?:-)
スティーブフォリー

2
不快な。コメントをありがとう、私は他の人がそれに遭遇すると確信しています。
オタク

@SteveFollyやります。何故なの?
ʇolɐǝzǝɥʇ前期比

@ʇolɐǝzǝɥʇqoqヘッダーファイルで指定しない限り、問題ありません。
smerlin 2015年

1
@ʇolɐǝzǝɥʇqoq避けてくださいusing namespace std;。それは悪い習慣と考えられています。「名前空間stdを使用する理由」を
LF


2

std::endlマニピュレータは同等です '\n'。ただし、std::endl常にストリームをフラッシュします。

std::cout << "Test line" << std::endl; // with flush
std::cout << "Test line\n"; // no flush

1

自分のラップトップ以外でプログラムを実行する場合は、このendlステートメントを使用しないでください。特に、たくさんの短い行を書いている場合や、私がファイルに単一の文字を頻繁に見た場合はそうです。の使用は、endlNFSのようなネットワーク化されたファイルシステムを強制終了することがわかっています。


それは紅潮によるものですか?それがどのように可能であるかがわかります。
オタクヘッド、

@Head確かに。また、ディスクIOパフォーマンスを破壊していることも確認しました。
sbi

0

参照これは出力専用I / Oマニピュレータ

std::endl改行文字を出力シーケンスosに挿入し、os.put(os.widen('\n'))次にを呼び出した場合と同様にフラッシュしos.flush()ます。

いつ使用するか:

このマニピュレータを使用して、出力行をすぐに生成できます。

例えば

長時間実行されているプロセスからの出力を表示する場合、複数のスレッドのログアクティビティまたは予期せずクラッシュする可能性のあるプログラムのログアクティビティ。

また

生成されたプロセスが画面I / Oを実行する場合、std :: systemを呼び出す前にstd :: coutの明示的なフラッシュも必要です。他のほとんどの通常の対話式I / Oシナリオでは、std :: cinからの入力、std :: cerrへの出力、またはプログラムの終了によりstd :: coutが強制的に呼び出されるため、std :: coutと共に使用するとstd :: endlは冗長になります。 。流す()。一部のソースから推奨されている「\ n」の代わりにstd :: endlを使用すると、出力パフォーマンスが大幅に低下する可能性があります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.