次のような関数宣言の場合
ostream& operator<< (ostream& os, const unsigned char* s);
何が返ってきたのか気になります。CPP リファレンスは、ostream オブジェクトを返すと述べています。しかし、なぜ単純な ostream ではなく ostream& なのですか?
ありがとうございました
次のような関数宣言の場合
ostream& operator<< (ostream& os, const unsigned char* s);
何が返ってきたのか気になります。CPP リファレンスは、ostream オブジェクトを返すと述べています。しかし、なぜ単純な ostream ではなく ostream& なのですか?
ありがとうございました
演算子がcopy や void ではなくa ostream&
(つまり、オブジェクトへの変更可能な参照) を返す理由は、たとえば、オブジェクトとしての一般的な例のように連鎖できるためです。ostream
std::cout
ostream
unsigned int i = 2;
std::cout << "This is a test to print " << "some text and maybe some numbers: " << i << std::endl;
ここではconst char*
、 anunsigned int
と stream modifer という 2 つの s を、別の行で区切ることなく連鎖させています。これにより、読みやすく、理解しやすくなっています。
最初の理由: std::ostream
s は一般にコピー可能ではありません (C++11 では、コピー コンストラクターは実際にはdelete
d です)。チェーンが機能しないため、とにかくコピーを返したくありません。
std::stringstream s;
s << "String1" << "String2";
最初のオペレーター呼び出しによって返されたコピーは、2 番目の呼び出しに必要な参照に変換できないため、コンパイルに失敗します。
参照の代わりに両方の値を作成しても機能しません。
std::stringstream s;
s << "String1" << "String2";
assert(s.str() == "String1String2");
コードはコンパイルさs
れますが、参照ではなくコピーによって渡されたため、これらの呼び出しの後もオブジェクトが変更されないため、アサートは失敗します。
2 番目の理由:stream
使用するすべての実際のオブジェクトは から派生しstd::ostream
ます。このパラメーターがコピーによって渡された場合、使用していたオブジェクトを効果的に失う場所でスライスが発生します。
これは、次のコードが機能しないことを意味します (参照渡しでコピーを返し、何らかの方法でコンパイル エラーを回避する場合)。
std::stringstream s;
s << "String1" << "String2" << std::endl;
assert(s == "String1String2");
s
のコピーを返すと、返されたオブジェクトはもはやオブジェクトではなく、それを呼び出すと一時オブジェクトに渡され、最後に破棄される"String1"
ため、この場合にのみ保持されます。std::stringstream
std::ostream
std::stringstream
operator<<
"String2"
これらが、値ではなく参照によって返すと考えることができる 2 つの重要な理由です。
そのように「os」を返すので、連鎖を行うことができます。
std::cout << "string1" << "string2" << std::endl;
単純なオブジェクトを返すには、コンパイラがオブジェクトのコピーを生成する必要がありますが、参照を返す必要はありません。