我应该使用c++操作符重载的哪个变体?,为什么

Which variation of C++ Operator Overloading should I use? And, why?

本文关键字:为什么 c++ 操作符 重载 我应该      更新时间:2023-10-16

这里给出了加法运算符(+)的3种重载形式。

我应该使用哪个变体,为什么?

class MyClass {
    int myInteger;
    double myDouble;
    public:
        MyClass(int i, double d) {
        myInteger = i;
        myDouble = d;
    }
    // Variation - 1
    //--------------
    MyClass operator +(MyClass rhsObj) {
        return MyClass(this->myInteger + rhsObj.myInteger, this->myDouble + rhsObj.myDouble);
    }
    // Variation - 2
    //--------------
    MyClass &operator +(MyClass &rhsObj) {
        rhsObj.myInteger = this->myInteger + rhsObj.myInteger;
        rhsObj.myDouble = this->myDouble + rhsObj.myDouble;
        return rhsObj;
    }
    // Variation - 3
    //--------------    
    MyClass &operator +(MyClass &rhsObj) {
        this->myInteger = this->myInteger + rhsObj.myInteger;
        this->myDouble = this->myDouble + rhsObj.myDouble;
        return *this;
    }
};

int main() {
    MyClass objOne(10, 10.5);
    MyClass objTwo(20, 20.5);
    MyClass objThree = objOne + objTwo;
}

赋值操作符(=)应该是什么情况?它应该使用哪种变体?

看你需要什么

首先,关于你的版本-显然

  • "Variation - 1"创建新对象,不触及两个操作数。
  • "Variation - 2"将结果存储在第二个操作数
  • "Variation - 3"将结果存储在"this"的第一个操作数中。

最有可能的是,变异- 1是最受欢迎的。

为什么?因为有副作用。如果你看到这样的表达式:

a = b + c;

无论a, bc的类型是什么,你会怎么想?我认为,abc的总和,而bc是不变的,我的意思是-与旧值。
假设,例如:

a = 5;
b = 6;
c = a + b;

你认为ab在求和后会变成11吗?当然,不能int重载operator+,但这只是一个简单直观的例子。


一个性能改进:在你的变体1中,而不是

MyClass operator+(MyClass rhsObj)

我会用

MyClass operator+(const MyClass& rhsObj)

这样你将避免一个额外的复制+你将告诉"客户端",使用你的代码,你不改变rhsObj,而只是使用它的值。

你真的需要onethree的变化。

MyClass的用户将期望它遵循最小惊奇原则,并且永远不会期望看到右侧由于加法而被修改。使用const将加强这一点,也将作为文档。如果您希望修改左侧,请使用+=。像这样:

// Plus: Modify neither the left nor the right
//--------------
MyClass operator +(const MyClass& rhsObj) const
{
    return MyClass(myInteger + rhsObj.myInteger, myDouble + rhsObj.myDouble);
}
// Increment: Modify the left
//--------------
MyClass& operator +=(const MyClass& rhsObj)
{
    myInteger += rhsObj.myInteger;
    myDouble += rhsObj.myDouble;
    return *this;
}

演示:http://ideone.com/8oarA

这三个+之间有细微的差别

第一个变体:

// Variation - 1
//--------------
MyClass operator+(MyClass rhsObj)
{
    return MyClass(this->myInteger + rhsObj.myInteger, this->myDouble + rhsObj.myDouble);
}

接受MyClass的对象作为输入,这意味着将rhsObj的副本传递给+,而原始对象rhsObj保持不变。这个重写返回一个新创建的MyClass对象。

第二个变体:

// Variation - 2
//--------------
MyClass & operator+(MyClass & rhsObj)
{
    rhsObj.myInteger = this->myInteger + rhsObj.myInteger;
    rhsObj.myDouble = this->myDouble + rhsObj.myDouble;
    return rhsObj;
}

以对rhsObj的引用作为输入,并在方法中更新rhsObj

最后一次变奏

// Variation - 3
//--------------    
MyClass & operator+(MyClass & rhsObj)
{
    this->myInteger = this->myInteger + rhsObj.myInteger;
    this->myDouble = this->myDouble + rhsObj.myDouble;
    return *this;
}

也以对rhsObj的引用作为参数,但是rhsObj在方法内部没有被修改。相反,调用+MyClass对象被更新。

从概念上讲,您希望返回一个新的对,因此在您的情况下,第一个变体可能更好。

或者你想返回其中一个参数,但是我发现操作符的名称混淆了。对于第三个变体,+=可能会更好。

我认为变异1将是最好的,主要有一个原因:如果你只有语句lhs + rhs;,你会期望/希望lhsrhs被修改吗?我知道在大多数(所有?)情况下我可能不会这么做。

因此排除了变型2和3