在C ++中定义加法运算符的正确方法

时间:2014-08-25 12:00:40

标签: c++ operators

我想知道在C ++中编写operator +的正确方法是什么(假设我正在为类c定义的对象定义加法运算符)?

c c::operator+(const c rhs) { /* do addition */ }

c c::operator+(const c& rhs) { /* do addition */ }

3 个答案:

答案 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的代码,编译器可能会优化传值值的情况,以便您生成的机器代码是相同的。