C++ 中的赋值运算符重载

Assignment Operator Overload in c++

我知道网络上有一个又一个重载赋值运算符的例子,但我花了最后几个小时试图在我的程序中实现它们并弄清楚它们是如何工作的,但我似乎无法理解这样做,任何帮助将不胜感激。

我正在尝试实现重载赋值运算符函数。

我有 3 个文件在工作,Complex.h 头文件,一个 Complex.cpp 定义文件,以及一个我用作驱动程序来测试我的 Complex class 的 .cpp 文件.

在 Complex.h 头文件中我的赋值运算符原型:

Complex &operator= (Complex&);

到目前为止,我对 .cpp 文件中重载运算符的定义是:

    Complex &Complex::operator=(Complex& first)
    {
         if (real == first.real && imaginary == first.imaginary)
             return Complex(real, imaginary);

         return first;
    };

我在函数中调用赋值运算符的方式是:

   x = y - z;

所以具体来说,我的问题是,当我用 x = y -z 调用重载赋值运算符时,当我 return 传入的值和我时,它不会将传入的值赋给 x我无法从网络上的众多示例和解释中找出原因,将不胜感激任何帮助,我提前感谢您的任何帮助。

重载的赋值运算符应该如下所示:

Complex &Complex::operator=(const Complex& rhs)
{
     real = rhs.real; 
     imaginary = rhs.imaginary;
     return *this;
};

你还应该注意,如果重载赋值运算符,你应该以相同的方式重载 Complex 的复制构造函数:

Complex::Complex(const Complex& rhs)
{
    real = rhs.real; 
    imaginary = rhs.imaginary;
};

我认为您需要以下运算符定义

Complex & Complex::operator =( const Complex &first )
{
     real = first.real;
     imaginary = first.imaginary;

     return *this;
};

您必须 return 引用分配给的对象。此外,参数应该是一个常量引用。在这种情况下,您可以将引用绑定到一个临时对象,或者您还必须编写一个移动赋值运算符。

在复制赋值运算符的实现中,您不会更改分配的对象。:) 您只需创建一个临时文件并return对此临时文件的引用或return对第一个文件的引用。

赋值接受两个对象,一个是要分配给的对象,另一个是具有所需值的对象。

分配应该:

  • 修改现有对象,对象被赋值给

赋值不应该:

  • 创建一个新对象
  • 修改具有所需值的对象。

假设我们正在处理的对象类型是:

struct S {
  int i;
  float f;
};

执行赋值的函数可能具有签名:

void assignment(S &left_hand_side, S const &right_hand_side);

它将被使用:

S a = {10, 32.0f};

S b;

assignment(b, a);

通知:

  • 左侧对象是可修改的,赋值将修改它,而不是创建一个新对象。
  • 右侧对象,即具有所需值的对象,不可修改。

此外,在C++中,内置的赋值操作是一个表达式而不是一个语句;它有一个值,可以用作子表达式:

int j, k = 10;

printf("%d", (j = k));

这里设置 j 等于 k,然后获取该赋值的结果并将其打印出来。需要注意的重要一点是,赋值表达式 的结果是被赋值给 的对象。没有创建新对象。在上面的代码中,打印了 j 的值(即 10,因为 j 刚刚从 k 中赋值 10)。

更新我们之前的赋值函数以遵循此约定导致签名如下:

S &assignment(S &left_hand_side, S const &right_hand_side);

一个实现看起来像:

S &assignment(S &left_hand_side, S const &right_hand_side) {
  // for each member of S, assign the value of that member in 
  // right_hand_side to that member in left_hand_side.
  left_hand_side.i = right_hand_side.i;
  left_hand_side.f = right_hand_side.f;

  // assignment returns the object that has been modified
  return left_hand_side;
}

注意这个赋值函数不是递归的;它不在赋值中使用自己,但它确实使用成员类型 的赋值 .

拼图的最后一块是让语法 a = b 起作用,而不是 assignment(a, b)。为此,您所要做的就是使 assignment () 成为成员函数:

struct S {
  int i;
  float f;

  S &assignment(S &left_hand_side, S const &right_hand_side) {
    left_hand_side.i = right_hand_side.i;
    left_hand_side.f = right_hand_side.f;
    return left_hand_side
  }
};

left_hand_side 参数替换为 *this:

struct S {
  int i;
  float f;

  S &assignment(S const &right_hand_side) {
    this->i = right_hand_side.i;
    this->f = right_hand_side.f;
    return *this;
  }
};

并将函数重命名为 operator=:

struct S {
  int i;
  float f;

  S &operator=(S const &right_hand_side) {
    this->i = right_hand_side.i;
    this->f = right_hand_side.f;
    return *this;
  }
};

int main() {
  S a, b = {10, 32.f};

  S &tmp = (a = b);

  assert(a.i == 10);
  assert(a.f == 32.f);

  assert(&tmp == &a);
}

要知道的另一件重要的事情是 = 符号用在一个不是赋值的地方:

S a;
S b = a; // this is not assignment.

这是'copy initialization'。它不使用 operator=。这不是任务。尽量不要混淆两者。

要记住的要点:

  • assignment 修改被赋值给的对象
  • 赋值不修改被赋值的对象。
  • 赋值不创建新对象。
  • 赋值不是递归的,除非复合对象的赋值对其包含的所有小成员对象使用赋值。
  • 赋值returns对象修改后的值
  • 复制初始化看起来有点像赋值,但与赋值关系不大。