C++ で関数を呼び出す場合()
、関数呼び出しと区別するために、関数名の後に が続きます。同じ方法で ストリーム マニピュレータ関数を呼び出せないのはなぜですか?
これが許可されない理由:
cout << "Hello!" << endl();
endl
変数が保持していません\n
か?
ありがとう!
C++ で関数を呼び出す場合()
、関数呼び出しと区別するために、関数名の後に が続きます。同じ方法で ストリーム マニピュレータ関数を呼び出せないのはなぜですか?
これが許可されない理由:
cout << "Hello!" << endl();
endl
変数が保持していません\n
か?
ありがとう!
ストリーム マニピュレータは関数です。そのため、それらは call 演算子を使用して呼び出すことができ()
ます。std::endl
ストリームで呼び出す方法は次のとおりです。
std::endl(std::cout);
これは、使用するストリームごとに呼び出す必要がある方法ですstd::endl
。これはstd::endl
、ストリーム オブジェクトへの参照を返す関数であるためです。これは非常に風変わりな方法なので、構文を簡素化する便利な関数があります。
std::ostream& operator<<(std::ostream& (*manip)(std::ostream&));
これは、operator<<()
左側にストリームを受け取り、右側にマニピュレーターを取る のオーバーロードです。std::endl
技術的には関数であるため、関数ポインターに変換できます。
このオーバーロードの実装内では、manip
先ほどお見せした方法とほとんど同じように呼び出されます。これにより、次のような構文が可能になります。
std::cout << "Hello, World" << std::endl;
先に進みstd::endl
、call 演算子を使用して呼び出すと、ストリームへの参照が返されます。引数としてoperator<<()
a を取る別のオーバーロードがあります。const void*
これは、誤って呼び出されたオーバーロードになります。
std::cout << std::endl(std::cout); // prints a newline then an address
マニピュレーターは、ストリーム オブジェクトの挿入 (<<) および抽出 (>>) 演算子と組み合わせて使用するために特別に設計された関数です。たとえば、次のようになります。
cout << boolalpha;
これらは依然として通常の関数であり、ストリーム オブジェクトを引数として使用して他の関数として呼び出すこともできます。次に例を示します。
boolalpha (cout);
したがって、コードで次のことができます
cout << "Hello!";
endl(cout);
それ以外の
cout << "Hello!" << endl;
ソース。
endl は \n を保持する変数ではありませんか?
いいえそうではありません。std::endl
グローバル名前空間で定義された関数です
template<typename _CharT, typename _Traits>
inline basic_ostream<_CharT, _Traits>&
endl(basic_ostream<_CharT, _Traits>& __os)
{ return flush(__os.put(__os.widen('\n'))); }
式std::cout << endl_or_something
の右辺<<
は への呼び出しのoperator<<
引数です (最初の引数はstd::ostream
暗黙的に)。したがって、 endl_or_something は、 の可能な引数の 1 つに変換できる int、double、またはその他の型である必要がありますoperator<<
。関数へのポインタを取るこの演算子のオーバーロードされたバージョンがあります ( への参照を取りstd::ostream
、への参照を返す関数std::ostream
):
// [27.6.2.5] formatted output
// [27.6.2.5.3] basic_ostream::operator<<
//@{
/**
* @brief Interface for manipulators.
*
* Manipulators such as @c std::endl and @c std::hex use these
* functions in constructs like "std::cout << std::endl". For more
* information, see the iomanip header.
*/
__ostream_type&
operator<<(__ostream_type& (*__pf)(__ostream_type&))
{
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// DR 60. What is a formatted input function?
// The inserters for manipulators are *not* formatted output functions.
return __pf(*this);
}
署名が一致するためstd::endl
、式で使用できます
std::cout << "Hello!" << std::endl;
または同等に
std::cout << "Hello!";
std::endl( std::cout);
ただし、このマニピュレータは、単純な改行が必要な場合に誤って使用されることが多く、バッファリングのパフォーマンスが低下することに注意してください。そのような場合は just を使用して"\n"
ください。
これが許可されない理由:
cout << "Hello!" << endl();
std::endl は std::ostream という 1 つの引数を取ります。次のように呼び出すことができることがわかります。
return __pf(*this);
意味
return std::endl( *this); // std::endl( std::cout);
std::endl
パラメータを取らないのバージョンはないため、次のように呼び出すことができます
std::endl()
表情で
std::cout << std::endl;
への引数を示し、operator<<
関数へのポインタとして渡され、本体で呼び出されoperator<<
ます。