为什么我们需要在重载>>和<<运算符时返回对 istream/ostream 的引用?

Why we need to return reference to istream/ostream while overloading >> and << operators?

本文关键字:gt lt istream ostream 引用 返回 重载 我们 运算符 为什么      更新时间:2023-10-16

如果我不返回dindout,会发生什么,实际上我正在读一本书,其中作者返回了引用的后台流

istream & operator>>(istream &din,vector &a)
{
    for(int i=0;i<size;i++)
    din>>a.v[i];
    return din;
}
ostream & operator<<(ostream &dout,vector &a)
{
    dout<<"("<<a.v[0];
    for(int i=1;i<size;i++)
    dout<<", "<<a.v[i];
    dout<<")";
    return dout;
}

原因是几个事实的结合。

  1. 您希望能够像中那样连锁输入和输出操作

    in  >> x >> y;
    out << z << std::precision(10) << t << std::endl;
    

    所以您必须再次返回允许operator<<的内容。

  2. 由于您希望操作员处理任何istream,即从std::istream派生的任何对象,因此无法定义

    operator<<(istream_type, object);    // take istream by value
    

    因为这只适用于特定的istream类型istream_type而不适用于一般的istream。为此,必须使用多态性,即取一个引用或一个指针(它将是从std::istream派生的类的引用或指针)。

  3. 由于您只有对istream的引用,因此不能返回istream对象本身(其类型可能在operator<<定义时尚未定义),而只能返回您已获得的引用。

    可以通过将operator<<定义为template并按值获取和返回istream_type来绕过这一限制,但这需要istream类型具有复制构造函数,而出于充分的原因,它可能没有复制构造函数。

  4. 为了发现多态性,原则上可以使用指针(指向流)而不是引用。然而,operator<<(stream*,const char*)在C++中不允许(至少有一个操作数必须是类或枚举类型)。

    因此,对于流指针,必须使用函数调用语法,然后返回C样式的fprintf(stream*, args...)

    此外,指针可以为null或悬空,这实际上是它们的默认状态(当在没有初始化器的情况下声明时),而引用可以被认为是有效的(如果没有初始化器,就不能声明它)。

在这种情况下,当返回引用时,您可以在链中组合运算符。例如

std::cout << "Hello " << "Rajat Verma";

这相当于操作员的以下呼叫

operator <<( operator <<( std::cout, "Hello" ), "Rajat Verma" );
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
              returns reference to std::cout 

还有一件事是,ostream和istream标准对象(如cout和cin)使用私有复制构造函数,因此它们应该通过引用而不是值返回

当您键入:cout<lt;矢量;cout的类型为ostream,因此当您使用"<<"时,它确实需要返回一个具有ostream类型的参数,以便cout工作