我想知道在C ++中编写operator +
的正确方法是什么(假设我正在为类c
定义的对象定义加法运算符)?
c c::operator+(const c rhs) { /* do addition */ }
或
c c::operator+(const c& rhs) { /* do addition */ }
答案 0 :(得分:2)
让我们举一个具体的例子:
class Int
{
int n_;
public:
// constructors...
Int & operator+=(Int const & rhs) { n_ += rhs.n_; return *this; }
Int & operator+=(Int && rhs) { n_ += rhs.n_; return *this; }
我们已经说明了化合物添加的两个重载碰巧是相同的,但是我们可以想象rvalue参考重载通常会提高效率。
现在如何写operator+
?一种选择是按价值采用RHS:
Int operator+(Int rhs) { return Int(*this) += std::move(rhs); }
这个版本肯定很容易编写和工作。这很方便,因为我们只需要一个重载来覆盖左值和右值参数。但请注意,此代码需要复制:构造Int(*this)
不能复制。因此,如果您绝对不想对用户施加任何不必要的成本,您可能希望加倍努力并重新实现非复合运算符:
Int operator+(Int const & rhs)
{ Int result(*this); result += rhs; return result; }
Int operator+(Int && rhs)
{ Int result(*this); result += std::move(rhs); return result; }
还有第三种选择:如果您的操作是可交换的,则可以返回按值的参数:
Int operator+(Int rhs) & { return rhs += *this; }
Int operator+(Int rhs) && { return rhs += std::move(*this); }
答案 1 :(得分:1)
定义操作+
(以及-
等其他类似操作)的推荐方法是定义+=
运算符,然后根据{{定义+
1}}。运算符+=
应该是该类的公共成员,应该通过const引用接受一个参数,并且应该返回对此的引用:
+=
然后很容易定义c& operator+=(const c& other)
{
... // modify the object in appropriate way, e.g. if it has a member x do
... // x += other.x;
return *this;
}
。它应该是在类外定义的全局函数:
operator+
当然,人们可以通过其他方式定义这些运算符,并且通常其他方式可能更好,但应该有一些理由这样做。否则最好坚持使用此默认值。
答案 2 :(得分:0)
通常,您应该更喜欢const引用版本,因为您已经保证不会更改引用的对象,并且它可以避免调用复制构造函数。除此之外,应该没有太大区别,除非你在运算符+()中做一些不安全的东西,在任何一种情况下都会破坏(比如获取传递的对象或其成员的地址,并对对象生命周期做出不满意的假设或有缺陷的副本构造函数实现)。
根据类c
的语义,复制构造函数可能还有一些不受欢迎的副作用,但只有作为c
类的作者才能知道。
此外,根据您在operator +()中所做的操作以及编译器可以直接看到哪个类c
的代码,编译器可能会优化传值值的情况,以便您生成的机器代码是相同的。