为什么我们将对象的引用作为参数传递给重载的输出运算符

时间:2014-05-02 23:04:59

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

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

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

如果我们不将其作为参考传递,我们会失败/获胜?

6 个答案:

答案 0 :(得分:2)

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

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

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

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

对于流,C ++流不可复制,这就是它们通过引用传递的原因。是非const引用,因为IO操作会更改流的内部状态。

答案 1 :(得分:1)

在一般情况下,将const&传递给函数会更有效率,因为它可以避免复制。

答案 2 :(得分:1)

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

对于除本机类型以外的任何其他内容,与通过引用访问对象相比,制作副本效率低是非常悲观的。

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

我们还可以预期某些对象的副本构造函数会产生副作用(例如不推荐使用的auto_ptr)。如果我们只想查询对象的状态,那么这些副作用将是不合需要的。对于auto_ptr,它们将导致在函数末尾删除由auto_ptr控制的对象。灾难性的。

一般规则是:

  • 如果您要阅读该对象,请传递一个const引用
  • 如果要修改对象,请传递引用(或指针)。
  • 如果您打算复制该对象,请将其传递给 值。
  • 如果你可以复制,那么要么通过const引用 (乐观地认为我们不需要复制)或按价值 (有理由相信需要副本)。

答案 3 :(得分:0)

答案显而易见。因为如果不这样做,那么实际对象将不会被修改。相反,将制作副本并修改副本,之后副本将被销毁。

答案 4 :(得分:0)

如果它不是const引用,那么你需要定义一个拷贝构造函数来使它正确,并且调用拷贝构造函数会花费更多的内存和CPU,这实际上是不必要的。

答案 5 :(得分:0)

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

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。

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