C++ 在运算符重载定义中,我经常看到哪些引用?

C++ 在运算符重载定义中,我经常看到哪些引用?,c++,class,reference,operator-overloading,C++,Class,Reference,Operator Overloading,例如,在OGRE3D引擎中,我经常看到 class_name class_name :: operator + (class_name & object) 而不是 class_name class_name :: operator + (class_name object) 这并不是说我更喜欢第二种形式,但是在输入中使用引用有什么特别的原因吗?是否有特殊情况需要使用引用而不是按值复制?还是性能问题?这是性能问题。通过引用传递通常比通过值传递便宜(它基本上等同于通过指针传递) 另一方面

例如,在OGRE3D引擎中,我经常看到

class_name class_name :: operator + (class_name & object)
而不是

class_name class_name :: operator + (class_name object)

这并不是说我更喜欢第二种形式,但是在输入中使用引用有什么特别的原因吗?是否有特殊情况需要使用引用而不是按值复制?还是性能问题?

这是性能问题。通过引用传递通常比通过值传递便宜(它基本上等同于通过指针传递)


另一方面,您可能希望
operator+
的参数为
const class\u name&object
,这样就不会从原始参数复制
object
。实际上,首选的方法是将
对象
作为
常量
传递,并将
运算符+
作为
常量成员运算符

class_name class_name :: operator + (const class_name& object) const;

当然,传递引用要比复制类的整个实例快得多。 此外,如果没有为类定义复制构造函数,那么复制它可能是危险的(例如,默认的复制构造函数将只复制指针,析构函数将删除它们)


将类传递给方法或运算符时,最好始终传递引用。您可以声明它为常量,以确保它未被修改以避免副作用。

建议在
操作符+=
方面实现
操作符+
。首先复制左参数,然后修改它,最后返回副本。由于您仍要复制左参数,因此不妨对左参数使用值调用:

class_name operator+(class_name x, const class_name& y)
{
    return x += y;
}
在C++0x中,应为结果启用移动语义:

#include <utility>

class_name operator+(class_name x, const class_name& y)
{
    return std::move(x += y);
}
#包括
类名称运算符+(类名称x,常量类名称y)
{
返回标准::移动(x+=y);
}
除了常规方法的“常规”调用约定外,我要注意的是,运算符有些特殊

使用
const&
代替传递值的主要原因是正确性(至少在我看来,性能是第二位的)。如果您的值可能是多态的,那么副本意味着对象切片,这通常是未定义的行为

因此,如果使用passby value,则可以清楚地向调用者声明对象将被复制,并且不应该是多态的

另一个原因可能是性能。如果类很小,并且它的复制构造函数很简单,那么复制它可能比使用间接寻址更快(想想类似int的类)。在其他情况下,传递值可能更快,但在非内联情况下,传递值更为罕见

然而,我确实认为这些都不是真正的原因,开发人员只是突然选择了这个

。。。因为真正的WTF(正如他们所说)是
操作符@
应该声明为自由函数,以允许左侧参数的参数提升


所以,如果他们不遵循这条规则,为什么他们要费心使用通常的参数传递方式呢?

已经有其他很好的答案了,但我想补充一点,对于所有函数,而不仅仅是重载运算符,传递
const class_name&
通常比传递
class_name
更可取。@aschepler:这是一样的“优化”可以通过
操作符=
重载来完成。传递值并获得临时值(不复制),然后实现
返回对象+=*this;
。当然,这是否实际更快是另一个主题:)+1,实际签名应该更接近
类型::操作符+(类型常量&)const
(注意两个
const
s)或者更好的
type操作符+(type lhs,type const&rhs){return lhs+=rhs;}
作为一个自由函数(第一个参数是值,第二个参数是常量引用)@Inverse:是的,这就是为什么我说“一般”“.Super-old thread,但我在google上找到了它,所以我想我应该添加一些信息:返回类型应该是const class_name,否则你可以编译以下代码:(a+b)=c;这显然在几乎所有情况下都是愚蠢的。”…因为真正的WTF(正如他们所说)是操作符@应该被声明为自由函数,以允许左侧参数的参数提升……”:你能更具体一点吗?我不知道你在说什么,我也找不到任何关于它的东西…@gokoon:很抱歉回复太晚。假设您有一个
Number
类,并定义
Number Number::operator+(int)const
。然后<代码>编号n(5);数量q=n+4正确,但编号r=4+n不会编译,因为没有将
(int,Number)
作为参数的
运算符+
。但是,如果您定义了
Number运算符+(Number,int)
Number运算符+(int,Number)
Number运算符+(Number,Number)
,则可以使用
Number
int
的任意组合作为参数。@gokoon:。。。此外,参数提升指的是将参数
int
转换为
Number
,例如,对于类方法,在左侧参数上是不可能的。@gokoon:很抱歉,
operator@
通常用作以
operator
开头的任何函数的占位符,如
operator+
operator-
operator*
,当人们谈论一种通常适用于所有函数的行为时。