【问题标题】:Must parameter of assignment operator be reference?赋值运算符的参数必须是引用吗?
【发布时间】:2011-02-25 19:17:27
【问题描述】:

在 C++ 中重载类的赋值运算符时,它的参数必须是引用吗?

例如,

class MyClass {
public:
...
MyClass & operator=(const MyClass &rhs);
...
}

可以吗

class MyClass {
public:
...
MyClass & operator=(const MyClass rhs);
...
}

?

谢谢!

【问题讨论】:

    标签: c++ reference assignment-operator


    【解决方案1】:

    重载赋值运算符的参数可以是任何类型,可以通过引用传递,也可以通过值传递(好吧,如果类型不是可复制构造的,那么显然不能通过值传递)。

    因此,例如,您可以有一个将int 作为参数的赋值运算符:

    MyClass& operator=(int);
    

    复制赋值运算符是赋值运算符的一种特殊情况。它是任何与类具有相同类型的赋值运算符,无论是通过值还是通过引用(引用可以是 const 或 volatile 限定的)。

    如果您没有显式实现某种形式的复制赋值运算符,那么编译器会隐式声明和实现一个。

    【讨论】:

    • 谢谢,詹姆斯!对于复制赋值运算符,是否有任何类类型不可复制?我认为所有类类型至少都有一个默认的复制构造函数?
    • @Tim: 当然:如果你有一个 private 用户声明的类的复制构造函数,那么复制构造函数将不可访问(除非你在成员函数中或该类的朋友)并且该类将不可复制构造。如果您声明了复制构造函数但未定义它,则该类根本不是可复制构造的(并且尝试复制构造实例会导致链接器错误)。这两种技术(通常一起使用)导致类不可复制构造。
    • 谢谢!我想知道在什么情况下需要一个不可复制的类?
    • @Tim:我能想到的最简单的例子是scoped_ptrboost.org/doc/libs/1_43_0/libs/smart_ptr/scoped_ptr.htm
    • @Tim:我创建了包装硬件资源的对象。如果那里允许复制构造函数,那会很尴尬。
    【解决方案2】:

    一般情况下,由您决定,没有必须。第一个变体是常见且“规范”的,适用于任何赋值运算符实现。

    当问题是速度时,我认为您应该阅读 this article 关于按值传递技术。这意味着在某些情况下,按值传递比通过 const 引用传递更有效。

    另外提一下,你的第二个变体不需要const关键字,因为按值传递就像创建了一个副本,所以原始对象肯定不会改变。

    【讨论】:

    • 谢谢科蒂!粗略看了下,但不太明白为什么按引用传递比按值传递慢?
    • 嗯,通常不是这样,但本文的重点是,如果您在通过引用传递对象后立即进行对象复制,这将比通过值传递并分配该副本慢,因为编译器优化。这实际上很棘手,但并非完全没有意义......
    【解决方案3】:

    C++ Operator Overloading Guidelines 建议,赋值运算符获取 const 引用。根据该站点的说法,原因是我们不想更改参数(从 const 开始),而只想更改运算符的左侧。因此,通过引用传递它可以节省时间。

    这也指出了为什么赋值运算符返回引用的原因 - 运算符链接。为了让a = (b = 1) 正常工作,(b = 1) 必须返回一个可以分配给= 的引用(=)。

    【讨论】:

      【解决方案4】:

      你知道异常安全分配的复制和交换习语吗?

      MyClass& operator=(const MyClass& rhs)
      {
          MyClass copy(rhs);
          swap(copy);
          return *this;
      }
      

      可以通过按值调用来简化(并且在某些情况下加快)实现:

      MyClass& operator=(MyClass copy)
      {
          swap(copy);
          return *this;
      }
      

      【讨论】:

      • 我想知道,考虑到复制和交换习语,如果在分配期间仍会创建副本(以防万一),不使用它有什么好处(使用 const 引用有什么好处) const 引用不是在调用时立即而是随后在正文中)?
      【解决方案5】:

      好的,我遇到了这个问题,但我找不到好的答案,所以我将分享我学到的东西。

      您可以按值传递,这没有任何问题。 (正如您在问题中所展示的那样。)

      但是我们通过 const 引用传递参数的原因是函数不会对被调用的值进行实际副本。它被引用,所以它只是指向该值在内存中的任何位置。

      这可以节省处理时间,特别是如果它具有数千个名称的大型... 在这种情况下,节省的时间几乎为零。

      对于 const,这可以确保函数的用户不会更改引用的值,因为它可能会被更改,因为您可以访问内存中的原始位置,因为它是通过引用传递的。 如果你的函数定义实际上改变了 const reference 调用的参数的值,那将是一个编译器错误,它不会让你这样做。因为当你输入 const 时,你是在告诉编译器这个值不能改变。

      【讨论】:

      • 考虑将这样的讨论带入 cmets。
      • 什么意思?抱歉,我是新人,我以为我写的是评论。
      • 一个问题或答案的左侧有一个很大的数字和上下箭头。每个下面都有一个链接,上面写着“add comment”。点击它会给你一个简单的文本框来输入评论,就像你刚刚使用的一样。您之前所做的是在页面底部名为“您的答案”的部分中输入答案。欢迎使用 StackOverflow :)
      • 好的,谢谢,我认为我写的是一个答案,因为所有其他答案都没有解释为什么我们使用 const refrense 他们只是重复了参考书上的内容。好吧,至少我是这样的感觉
      猜你喜欢
      • 2011-03-07
      • 1970-01-01
      • 2018-04-24
      • 2018-02-21
      • 2015-04-16
      • 1970-01-01
      • 2011-12-12
      • 2014-12-26
      • 1970-01-01
      相关资源
      最近更新 更多