【问题标题】:Why do we pass a reference to the object as an argument to the overloaded output operator为什么我们将对象的引用作为参数传递给重载的输出运算符
【发布时间】:2014-05-02 23:04:59
【问题描述】:

为什么作为引用而不只是对象的副本如此重要?例如:

ostream& operator<<(ostream& out, const X & _class);
ostream& operator<<(ostream& out, const X   _class);

如果我们不将它作为参考传递,我们会输/赢什么?

【问题讨论】:

  • 否则它将创建 ostream 的副本并在其上执行您的逻辑,这可能不是您想要的。
  • 这就是我要问的,这是一个简单的输出重载!我不想改变任何我只想 cout 的东西。
  • 我不想更改输出重载的对象
  • 有时这是必要的,因为X 对象不可复制。如果X 有一个重要的复制构造函数,那么它就是一种优化。在其他情况下,它是一种微观优化,甚至可能是一种“悲观化”。

标签: c++ operator-overloading pass-by-reference


【解决方案1】:

一般来说,const&amp; 是首选,因为除了易于复制的类型(例如基本类型)之外,复制成本很高(我记得,并非总是如此)。但注意传值是指函数的内部值与传递给函数的值无关。这允许编译器做一些假设并在某些情况下执行更好的优化。所以在某些情况下,按值传递会更好。

其中一种情况是当您需要传递参数的副本时:

void f( T param )
{
    /* do something mutable with param */
}

在这种情况下,按值传递比通过 const 引用 + 手动传递更可取,因为编译器可以根据值语义进行假设,并优化代码。规则是:让编译器决定如何按值传递。

在流的情况下,C++ 流是不可复制的,这就是它们通过引用传递的原因。是非常量引用,因为 IO 操作会更改流的内部状态。

【讨论】:

  • +1 并且const 引用向其他人表明输出运算符不会改变其操作数。
【解决方案2】:

“合理的悲观主义”将总结我们为什么这样做,以及为什么我们更愿意为任何我们不需要副本的非平凡对象传递引用。

我们可以相当悲观地认为,对于原生类型以外的任何东西,与通过引用访问对象相比,制作副本效率低下。

我们还可以预期,并非所有对象都是可复制的,因此编写一个要求我们的参数可复制的函数不仅可能效率低下,还可能导致程序无法编译。

我们还可以预期某些对象的复制构造函数会产生副作用(例如已弃用的 auto_ptr)。如果我们只想查询一个对象的状态,这些副作用是不可取的。在 auto_ptr 的情况下,它们将导致在函数结束时删除由 auto_ptr 控制的对象。灾难性的。

一般规则是:

  • 如果您只是要读取对象,请传递一个 const 引用
  • 如果要修改对象,请传递引用(或指针)。
  • 如果您肯定要制作对象的副本,请将其传递 价值。
  • 如果您可以制作副本,则通过 const 引用传递 (乐观地认为我们不需要复制)或按价值计算 (有理由相信需要该副本)。

【讨论】:

    【解决方案3】:

    在一般情况下,将const&amp; 传递给函数更有效,因为它避免了复制。

    【讨论】:

      【解决方案4】:

      答案很明显。因为如果你不这样做,那么实际的对象将不会被修改。相反,将制作副本并修改副本,然后副本将被销毁。

      【讨论】:

      • 参数为const,所以无论是引用传递还是值传递都不会被修改。
      • OP指的是第二个参数。
      【解决方案5】:

      如果不是 const 引用,那么你需要定义一个拷贝构造函数来使其正确,而调用拷贝构造函数显然会消耗更多的内存和 CPU,这确实是不必要的。

      【讨论】:

        【解决方案6】:

        让我直说吧。当您传递对象的引用并在重载运算符的定义中修改对象内容时,同样会反映在对象上。例如:(尽管对于复数来说,+ 运算符永远不会以这种方式重载,但这个例子只是为了证明一个观点)。说一个重载的 + 运算符

        complex1& operator+(complex1 a)
            {
                a.real = a.real+1;
                real=real+a.real;
                img=img+a.img;
                return *(this);
            }
        
        int main()
        {
            complex1 c1(1,2),c2(2.4,6.3);
            complex1 c3 = c1+c2;
            cout<<c2;
            return 0;
        }
        

        这里,在 c2 的实部所做的更改(即加 1)在打印时不会反映,如果没有通过引用,仍然是 2.4。因此,传递一个引用会将其实部的值增加 1。

        其次,传递引用更有效,因为您只传递对该对象的引用,而不是通过值传递对象的所有属性都被复制。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2014-03-12
          • 2012-09-05
          • 2014-07-24
          • 1970-01-01
          • 1970-01-01
          • 2013-06-06
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多