web-dev-qa-db-ja.com

C ++: "std :: endl"と "\ n"

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

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

...だから私もいつもやっています。しかし、私はこのような作業中の開発者からのコードをたくさん見ました:

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

一方を他方よりも優先する技術的な理由はありますか、それとも単にコーディングスタイルの問題なのでしょうか。

498
Head Geek

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

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

424
David Thornley

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

std::cout << std::endl;

と同等です

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

そう、

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

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

他の主張とは反対に、\n文字は、ストリームがファイルに送られる場合に限り、正しいプラットフォームの行末シーケンスにマッピングされます(std::cinstd::coutは特別だがファイルのままです)。

214
Martin York

パフォーマンスの問題があるかもしれません、std::endlは出力ストリームのフラッシュを強制します。

40
Martin Beckett

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

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

ISO/IEC 9899:201倍

7.21.3§7

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

7.21.3§3

ストリームがバッファリングされていない場合、文字はできるだけ早く送信元または送信先に表示されるように意図されています。そうでなければ、文字は累積され、ブロックとしてホスト環境との間で送受信される可能性があります。ストリームが完全にバッファされると、文字はバッファがいっぱいになったときにブロックとしてホスト環境との間で送受信されることを意図しています。ストリームがラインバッファされるとき、文字は改行文字に遭遇したときにブロックとしてホスト環境との間で送受信されることを意図しています。さらに、文字は、バッファーがいっぱいになったとき、バッファリングされていないストリームで入力が要求されたとき、またはホスト環境からの文字の送信を必要とするラインバッファー付きストリームで入力が要求されたときに、ホスト環境にブロックとして送信されます。 。これらの特性のサポートは実装定義であり、setbufおよびsetvbuf関数を介して影響を受ける可能性があります。

これは、std::coutstd::cinが完全にバッファリングされていることを意味します/ の場合に限り、 は非インタラクティブデバイスを参照しています。言い換えると、stdoutが端末に接続されている場合、動作に違いはありません。

ただし、std::cout.sync_with_stdio(false)が呼び出された場合、'\n'は対話型デバイスに対してもフラッシュを引き起こしません。そうでなければ'\n'はファイルへのパイピングを除いてstd::endlと同等です: c ++ ref on std :: endl

26
Emily L.

あなたがstd::endlを使うつもりならば、そこに暗示されている別の関数呼び出しがあります

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

a)演算子<<を一度呼び出します。
b)演算子<<を2回呼び出します。

23
Nathan

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

18
Ferruccio

大したことではありませんが、 endlは動作しません in boost :: lambda

(cout<<_1<<endl)(3); //error

(cout<<_1<<"\n")(3); //OK , prints 3
11
Özgür

あなたがQtとendlを使うなら、あなたは誤って間違ったendlを使うかもしれません、今日私に起こり、私は..WTFのようでしたか?

#include <iostream>
#include <QtCore/QtCore> 
#include <QtGui/QtGui>
//notice that i dont have a "using namespace std;"
int main(int argc, char** argv)
{
    QApplication qapp(argc,argv);
    QMainWindow mw;
    mw.show();
    std::cout << "Finished Execution !" << endl << "...";
    // Line above printed: "Finished Execution !67006AB4..."
    return qapp.exec();
}

私はstd::endlを書くべきだったので、もちろんそれは私のミスでした、 endl、qt、using namespace std;を使用する場合、正しいendlが使用されるかどうかは、インクルードファイルの順序によって異なります。*

もちろん、名前空間を使用するようにQtを再コンパイルすることもできますので、上記の例ではコンパイルエラーになります。

編集:言及を忘れて、QtのendlはQtCoreの一部である "qtextstream.h"で宣言されています

* EDIT2:std::coutまたはネームスペースendlusingがある場合、C++は正しいstdを選択します。これは、std::endlstd::coutと同じ名前空間にあるため、C++のADLメカニズムがstd::endlを選択するためです。

9
smerlin

見やすいので、いつもstd :: endlを使う習慣があります。

2
Zee JollyRoger

With reference これは出力専用の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 :: endlはstd :: coutと共に使用すると冗長です。 。流す()。一部のソースによって推奨されている '\ n'の代わりにstd :: endlを使用すると、出力パフォーマンスが著しく低下する可能性があります。

0
Kaleem Ullah

自分のラップトップ以外のものであなたのプログラムを走らせるつもりなら、決してendlステートメントを使わないでください。特にあなたが短い行をたくさん書いているか、私がファイルに単一の文字を見たことがあるような場合。 endlの使用は、NFSのようなネットワークファイルシステムを殺すことが知られています。

0

endlマニピュレータは'\'と同等です。しかしendlは常にストリームをフラッシュします。

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