5

对于函数声明,如

ostream& operator<< (ostream& os, const unsigned char* s);

我想知道退回了什么。CPP 参考说它返回 ostream 对象。但为什么它是 ostream& 而不是简单的 ostream?

谢谢

4

4 回答 4

5

运算符返回 a ostream&(即对ostream对象的可修改引用)而不是副本或 void 的原因是它允许链接,例如,一个带有std::coutasostream对象的常见示例:

unsigned int i = 2;
std::cout << "This is a test to print " << "some text and maybe some numbers: " << i << std::endl;

在这里,我们链接了两个const char*s,一个unsigned int和一个流修饰符,而不必用单独的行将它们分开,这样更易​​于阅读和理解。

于 2013-06-20T14:47:15.800 回答
4

第一个原因:std::ostreams 通常不可复制(在 C++11 中,复制构造函数实际上是deleted)。无论如何,您都不想返回副本,因为链接不起作用:

    std::stringstream s;
    s << "String1" << "String2";

将无法编译,因为第一个运算符调用返回的副本不能转换为第二个调用所需的引用。
制作两个值而不是引用也行不通:

    std::stringstream s;
    s << "String1" << "String2";
    assert(s.str() == "String1String2");

您的代码将编译,但断言将失败,因为s在这些调用之后对象保持不变,因为它是通过复制而不是通过引用传递的。

第二个原因:您将使用的所有实际stream对象都派生自std::ostream. 如果此参数是通过副本传递的,那么您将在有效丢失正在使用的对象的地方进行切片。
这意味着以下代码将不起作用(如果通过引用传递但通过复制返回并且以某种方式绕过编译错误?):

    std::stringstream s;
    s << "String1" << "String2" << std::endl;
    assert(s == "String1String2");

s只会"String1"在这种情况下成立,因为当您返回 的std::stringstreamby 副本时std::ostream,返回的对象不再是一个std::stringstream对象,并且调用operator<<它会传递"String2"到一个临时对象,该对象最终会被销毁。

这是我能想到的按引用而不是按值返回的两个重要原因。

于 2013-06-20T14:57:06.583 回答
1

返回简单对象需要编译器生成对象副本,但返回引用不需要。

于 2013-06-20T14:47:09.957 回答
1

因为您像这样返回“os”,所以您可以进行链接;

std::cout << "string1" << "string2" << std::endl;
于 2013-06-20T14:46:39.730 回答