赋值运算符的参数必须是引用吗?
Posted
技术标签:
【中文标题】赋值运算符的参数必须是引用吗?【英文标题】: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);
...
?
谢谢!
【问题讨论】:
【参考方案1】:重载赋值运算符的参数可以是任何类型,可以通过引用传递,也可以通过值传递(好吧,如果类型不是可复制构造的,那么显然不能通过值传递)。
因此,例如,您可以有一个将int
作为参数的赋值运算符:
MyClass& operator=(int);
复制赋值运算符是赋值运算符的一种特殊情况。它是任何与类具有相同类型的赋值运算符,无论是通过值还是通过引用(引用可以是 const 或 volatile 限定的)。
如果您没有显式实现某种形式的复制赋值运算符,那么编译器会隐式声明和实现一个。
【讨论】:
谢谢,詹姆斯!对于复制赋值运算符,是否有任何类类型不可复制?我认为所有类类型至少都有一个默认的复制构造函数? @Tim: 当然:如果你有一个 private 用户声明的类的复制构造函数,那么复制构造函数将不可访问(除非你在成员函数中或该类的朋友)并且该类将不可复制构造。如果您声明了复制构造函数但未定义它,则该类根本不是可复制构造的(并且尝试复制构造实例会导致链接器错误)。这两种技术(通常一起使用)导致类不可复制构造。 谢谢!我想知道在什么情况下需要一个不可复制的类? @Tim:我能想到的最简单的例子是scoped_ptr
:boost.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
”。点击它会给你一个简单的文本框来输入评论,就像你刚刚使用的一样。您之前所做的是在页面底部名为“您的答案”的部分中输入答案。欢迎使用 *** :)
好的,谢谢,我认为我写的是一个答案,因为所有其他答案都没有解释为什么我们使用 const refrense 他们只是重复了参考书上的内容。好吧,至少我是这样的感觉以上是关于赋值运算符的参数必须是引用吗?的主要内容,如果未能解决你的问题,请参考以下文章