对于像
这样的功能声明ostream& operator<< (ostream& os, const unsigned char* s);
我想知道返回了什么。 CPP引用表示它返回ostream对象。但为什么它是ostream&amp;而不是简单的ostream?
谢谢
答案 0 :(得分:5)
运算符返回ostream&
(即对ostream
对象的可修改引用)而不是副本或void的原因是它允许链接,例如,一个常见示例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*
,一个unsigned int
和一个流修改器,而不必用单独的行分隔它们,这样可以更好地阅读和理解。
答案 1 :(得分:4)
第一个原因:std::ostream
一般不可复制(在C ++ 11中,复制构造函数实际上是delete
d)。您无论如何都不想返回副本,因为链接不起作用:
std::stringstream s;
s << "String1" << "String2";
将无法编译,因为第一个操作员调用返回的副本将无法转换为第二个调用所需的引用。
同时使两个值而不是引用也不起作用:
std::stringstream s;
s << "String1" << "String2";
assert(s.str() == "String1String2");
您的代码将编译,但断言将失败,因为对象s
在这些调用后仍未修改,因为它是通过复制而不是通过引用传递的。
第二个原因:您将使用的所有实际stream
对象都来自std::ostream
。如果此参数是通过副本传递的,那么您将获得slicing,从而有效地丢失了您正在使用的对象
这意味着下面的代码不起作用(如果通过引用传递但是通过复制返回 - 以某种方式绕过编译错误?):
std::stringstream s;
s << "String1" << "String2" << std::endl;
assert(s == "String1String2");
在这种情况下, s
只会保留"String1"
,因为当您按std::stringstream
的副本返回std::ostream
时,返回的对象不再是std::stringstream
对象和调用operator<<
将"String2"
传递给临时对象,该对象最终会被破坏。
这是我可以想到的两个重要原因,即通过引用而非价值回归。
答案 2 :(得分:1)
因为你像那样返回“os”,你可以进行链接;
std::cout << "string1" << "string2" << std::endl;
答案 3 :(得分:1)
返回简单对象需要编译器生成对象副本,但返回引用不需要。