【问题标题】:Why we need to return reference to istream/ostream while overloading >> and << operators?为什么我们需要在重载 >> 和 << 运算符时返回对 istream/ostream 的引用?
【发布时间】:2015-05-08 21:32:34
【问题描述】:

如果我不返回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;
}

【问题讨论】:

    标签: c++ reference stream operator-overloading


    【解决方案1】:

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

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

    这相当于运算符的以下调用

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

    【讨论】:

      【解决方案2】:

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

      【讨论】:

        【解决方案3】:

        原因是几个事实的结合。

        1. 您希望能够像中一样链接输入和输出操作

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

          所以你必须返回允许operator&lt;&lt;再次的东西。

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

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

          因为这仅适用于特定 istream 类型 istream_type,但不适用于通用 istream。为此必须使用多态性,即采用引用或指针(这将是从std::istream 派生的类的引用或指针)。

        3. 由于您只有对 istream 的引用,因此您不能返回 istream 对象本身(它可能是在 operator&lt;&lt; 的定义点甚至没有定义的类型),而只能返回您拥有的引用。

          可以通过定义 operator&lt;&lt;template 并按值获取并返回 istream_type 来绕过此限制,但这需要 istream 类型具有复制构造函数,它可能没有很好的理由。

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

          因此,对于流指针,必须使用函数调用语法,而您又回到了 C 风格 fprintf(stream*, args...)

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

        【讨论】:

        • 我不确定你关于指针的最后一个论点是否切中要害。如果这些运算符返回指针,我们将不得不像 *(*(out &lt;&lt; foo) &lt;&lt; bar) &lt;&lt; baz; 一样调用它们——当然没有人会想要那种语法混乱。
        • @TheParamagneticCroissant 。你没明白我的意思。我编辑了答案。一个人可以(拥有)使用(d)指针而不是引用everywhere,包括标准库,它可以像引用一样工作,预计会出现空指针和/或悬空指针的问题。
        • 指针的“默认状态”不是“NULL or dangling”,不使用指针很容易创建悬空引用。将引用与流函数一起使用的原因是允许链接,也因为使用引用允许操作员假设对象存在(即调用者负责提供有效引用,操作员不需要检查有效性,例如它会带有一个指针)
        • @Rob,我认为您的最后一点是我所说的空指针或悬空指针。没有初始化器声明的指针为空或悬空。没有初始化器就不能声明引用。
        • @Walter 如果在参数中使用指针,则不能在右值流上调用这些运算符。我见过 C++11 之前的代码在做std::stringstream(the_string) &gt;&gt; the_int
        【解决方案4】:

        当您键入时: cout

        【讨论】:

          猜你喜欢
          • 2013-10-10
          • 2020-02-10
          • 1970-01-01
          • 1970-01-01
          • 2012-04-23
          • 2016-07-28
          • 1970-01-01
          • 2011-08-31
          相关资源
          最近更新 更多