これらはストリーム挿入(またはの場合は抽出)と呼ばれ、istream >>実際には左シフト演算子と右シフト演算子のセマンティックオーバーロードです。
したがって、この:
int x = 1 << 1;
少しシフトですが、これは:
std::cout << x;
ストリーム挿入です。次のように明示的に書き出すことができます。
operator <<(std::cout, x);
まったく同じ結果が得られます。ストリーム挿入演算子の従来の形式(ユーザー定義型ではオーバーロードされる可能性があるため、独自の演算子を作成することは珍しくありません)は次のとおりです。
std::ostream& operator <<(std::ostream&, T value);
出力ストリームは(参照により)返されるため、呼び出しを連鎖させることができます。例は次のように変換されます。
operator<< (
operator<< (
operator<<(std::cout, "firstvalue"),
firstvalue
),
std::endl
);
ああ、そして... std::cout(std::cerrなど)は関数ではありません:それらはグローバルオブジェクトです。ここでの関数は、オーバーロードされた<<演算子です。FILE *stdout, *stderrそれらを同等のものと考えてください。
printfetよりもC++iostreamsにはいくつかの利点があります。al:
- 型安全性:オーバーロード解決によりコンパイル時
"%f"に関数が自動的に選択されるため、誤って整数を出力してガベージを取得することはできません。std::ostream& operator<<(std::ostream&, double)
- ユーザー定義型のサポート:ウィジーな新しいクラスのストリーム挿入演算子を記述でき、どこでも機能します
- ストリームの抽象化:同じオーバーロードを使用して(1回だけ書き込む)、stdoutとstderr(
cout/ cerr)、およびファイル(std::ofstream)と文字列(std::ostringstream)にフォーマットできます。printf//を個別にfprintf処理する必要はありません。snprintf
いくつかの欠点もあります。
- パフォーマンス:すべての抽象化と、実行時に構成されるロケールシステムの一般性にはいくらかのペナルティがあります
- 冗長性:少なくとも、ですでにサポートされているプリミティブ型
printfの場合、フォーマット文字列ははるかに簡潔で表現力に富んでいます。