多くの C++ 書籍には、次のようなサンプル コードが含まれています...
std::cout << "Test line" << std::endl;
…だから私もずっとそうしてきた。しかし、代わりに次のような作業中の開発者からの多くのコードを見てきました。
std::cout << "Test line\n";
どちらかを優先する技術的な理由はありますか、それとも単にコーディング スタイルの問題ですか?
多くの C++ 書籍には、次のようなサンプル コードが含まれています...
std::cout << "Test line" << std::endl;
…だから私もずっとそうしてきた。しかし、代わりに次のような作業中の開発者からの多くのコードを見てきました。
std::cout << "Test line\n";
どちらかを優先する技術的な理由はありますか、それとも単にコーディング スタイルの問題ですか?
ファイルがテキストモードで開いていると仮定すると、行末の文字の変化は重要ではありません。これは、バイナリを要求しない限り取得できるものです。コンパイルされたプログラムは、コンパイルされたシステムに対して正しいものを書き出します。
唯一の違いはstd::endl
、出力バッファをフラッシュすることとフラッシュ'\n'
しないことです。バッファを頻繁にフラッシュしたくない場合は、を使用して'\n'
ください。その場合(たとえば、すべての出力を取得したいが、プログラムが不安定な場合)、を使用しますstd::endl
。
違いは次のように説明できます。
std::cout << std::endl;
と同等です
std::cout << '\n' << std::flush;
それで、
std::endl
出力に即時フラッシュを強制する場合に使用します。\n
を使用している場合はおそらくそうではありません)。<<
私は\n
ほとんどの行で使用します。
次にstd::endl
、段落の最後で使用します(ただし、これは単なる習慣であり、通常は必要ありません)。
他の主張とは異なり、\n
文字は、ストリームがファイルに送られる場合にのみ、正しいプラットフォームの行末シーケンスにマップされます(std::cin
そしてstd::cout
、特別であるがファイル(またはファイルのようなもの)である場合のみ)。
パフォーマンスの問題が発生している可能性がありstd::endl
、出力ストリームを強制的にフラッシュします。
使用する場合は、そこに別の関数呼び出しが含まれていますstd::endl
a) std::cout << "Hello\n";
b) std::cout << "Hello" << std::endl;
a) オペレーターを 1 回呼び出します<<
。
b) オペレーター<<
を 2 回呼び出します。
これについて標準で読んだことを思い出したので、ここに行きます:
標準ストリームがどのように動作するかを定義する C11 標準を参照してください。C++ プログラムが CRT とやり取りするため、ここでは C11 標準がフラッシュ ポリシーを管理する必要があります。
ISO/IEC 9899:201x
7.21.3 §7
プログラムの起動時に、3 つのテキスト ストリームが事前定義されており、明示的に開く必要はありません。標準入力 (従来の入力を読み取るため)、標準出力 (従来の出力を書き込むため)、および標準エラー (診断出力を書き込むため) です。最初に開いたとき、標準エラー ストリームは完全にバッファリングされていません。標準入力および標準出力ストリームは、ストリームが対話型デバイスを参照していないと判断できる場合にのみ、完全にバッファリングされます。
7.21.3 §3
ストリームがバッファリングされていない場合、文字はソースまたは宛先からできるだけ早く表示されるように意図されています。そうしないと、文字が蓄積され、ブロックとしてホスト環境との間で送受信される可能性があります。ストリームが完全にバッファリングされている場合、文字は、バッファがいっぱいになったときにブロックとしてホスト環境との間で送受信されることを意図しています。ストリームが行バッファリングされている場合、文字は、改行文字が検出されたときにブロックとしてホスト環境との間で送受信されることを意図しています。さらに、文字は、バッファがいっぱいになったとき、バッファされていないストリームで入力が要求されたとき、またはホスト環境からの文字の送信を必要とするラインバッファ付きストリームで入力が要求されたときに、ブロックとしてホスト環境に送信されることを意図しています。 .
これは、非対話型デバイスを参照している場合にのみ、std::cout
とstd::cin
が完全にバッファリングされることを意味します。つまり、stdout が端末に接続されている場合、動作に違いはありません。
ただし、std::cout.sync_with_stdio(false)
が呼び出された場合'\n'
、対話型デバイスに対してもフラッシュは発生しません。それ以外の場合は、ファイルにパイプしない限り'\n'
と同等です: c++ ref on std::endl。std::endl
どちらも適切な行末文字を書き込みます。その endl に加えて、バッファがコミットされます。不要なコミットがパフォーマンスに影響を与える可能性があるため、通常、ファイル I/O を実行するときに endl を使用することは望ましくありません。
大したことではありませんが、endl はboost::lambdaでは機能しません。
(cout<<_1<<endl)(3); //error
(cout<<_1<<"\n")(3); //OK , prints 3
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
(これは正しいでしょう)、どうやらqtextstream.h(QtCoreの一部)でendl
定義された関数があるようです。
潜在的な名前空間の問題を完全に回避する"\n"
代わりに使用します。endl
これは、(Qt がデフォルトで行うように) シンボルをグローバル名前空間に入れることがなぜ悪い考えなのかの良い例でもあります。
std::endl は見やすいため、常に使用する習慣がありました。
自分のラップトップ以外でプログラムを実行する場合は、決してこのendl
ステートメントを使用しないでください。特に、短い行をたくさん書いている場合や、1 つの文字をファイルに書き込んでいることがよくあります。の使用は、endl
NFS のようなネットワーク化されたファイル システムを強制終了することが知られています。