在 C++ 中重载类的赋值运算符时,它的参数必须是引用吗?
例如,
class MyClass {
public:
...
MyClass & operator=(const MyClass &rhs);
...
}
是真的吗
class MyClass {
public:
...
MyClass & operator=(const MyClass rhs);
...
}
?
谢谢!
在 C++ 中重载类的赋值运算符时,它的参数必须是引用吗?
例如,
class MyClass {
public:
...
MyClass & operator=(const MyClass &rhs);
...
}
是真的吗
class MyClass {
public:
...
MyClass & operator=(const MyClass rhs);
...
}
?
谢谢!
重载赋值运算符的参数可以是任何类型,并且可以通过引用或值传递(好吧,如果类型不是可复制构造的,那么显然不能通过值传递)。
因此,例如,您可以有一个将 anint
作为参数的赋值运算符:
MyClass& operator=(int);
复制赋值运算符是赋值运算符的一种特殊情况。它是任何与类具有相同类型的赋值运算符,无论是通过值还是通过引用(引用可以是 const 或 volatile 限定的)。
如果您没有显式实现某种形式的复制赋值运算符,那么编译器会隐式声明和实现一个。
通常,由您决定,没有必须。第一个变体是常见的和“规范的”,适用于任何赋值运算符实现。
当问题是速度时,我认为您应该阅读这篇关于按值传递技术的文章。这意味着在某些情况下,按值传递比通过 const 引用传递更有效。
还要提一下,您的第二个变体不需要const
关键字,因为按值传递就像创建了一个副本,所以原始对象肯定不会改变。
C++ 运算符重载指南建议,赋值运算符获取 const 引用。根据该站点的说法,原因是我们不想更改参数(因为 const),而只想更改运算符的左侧。因此,通过引用传递它可以节省时间。
它还指出了为什么赋值运算符返回引用的原因 - 运算符链接。为了开始a = (b = 1)
工作,有必要(b = 1)
返回一个可以分配(=
)的引用a
。
你知道异常安全分配的复制和交换习语吗?
MyClass& operator=(const MyClass& rhs)
{
MyClass copy(rhs);
swap(copy);
return *this;
}
可以通过按值调用来简化(并且在某些情况下加快)实现:
MyClass& operator=(MyClass copy)
{
swap(copy);
return *this;
}
好的,我遇到了这个问题,我找不到一个好的答案,所以我将分享我学到的东西。
您可以按值传递,这没有任何问题。(正如您在问题中所展示的那样。)
但是我们通过 const 引用传递参数的原因是函数不会对被调用的值进行实际复制。它被引用,所以它只是指向该值在内存中的任何位置。
这节省了处理时间,特别是如果它有成千上万个名字的大东西......在这种情况下,节省的时间几乎没有。
对于 const,这可以确保函数的用户不会更改引用的值,因为它可能会被更改,因为您可以访问内存中的原始位置,因为它是通过引用传递的。如果您的函数定义实际上更改由 const reference 调用的参数的值,这将是编译器错误,它不会让你这样做。因为当你输入 const 时,你是在告诉编译器这个值不能改变。