在 C++ 中实现赋值运算符重载

Jinku Hu 2023年10月12日
在 C++ 中实现赋值运算符重载

本文将介绍几种如何在 C++ 中实现赋值运算符重载的方法。

使用复制赋值运算符在 C++ 中实现重载的赋值运算符

C++ 提供了重载运算符的功能,这是在特定类上调用内置运算符时调用自定义函数的一种常用方法。这些功能应有一个特殊的名称,以 operator 开头,后跟特定的操作符符号本身。例如,可以使用名为 operator= 的函数来实现自定义赋值运算符。赋值运算符通常应返回对其左侧操作数的引用。请注意,如果用户未明确定义副本赋值运算符,则编译器会自动生成一个。当该类不包含在堆内存上手动赋值的任何数据成员时,生成的版本将具有足够的功能。它甚至可以通过将每个元素赋值给相应的对象成员来处理数组成员。但是,在处理动态内存数据成员时,它有缺点,如下面的示例代码所示。

#include <iostream>
#include <string>
#include <utility>
#include <vector>

using std::cout;
using std::endl;
using std::string;
using std::vector;

class Person {
 public:
  Person() {
    name = new string;
    surname = new string;
  };
  Person(string n, string s) {
    name = new string(std::move(n));
    surname = new string(std::move(s));
  }
  Person(Person &p) {
    name = new string(*p.name);
    surname = new string(*p.surname);
  }

  ~Person() {
    delete name;
    delete surname;
  }

  void renamePerson(const string &n, const string &s) {
    name->assign(n);
    surname->assign(s);
  };

  void printPerson() { cout << *name << " " << *surname; }

 private:
  string *name;
  string *surname;
};

int main() {
  Person P1("Buddy", "Rich");
  Person P2 = P1;

  P1.printPerson();
  cout << endl;
  P2.printPerson();
  cout << endl;

  P1.renamePerson("Jay", "Roach");

  P1.printPerson();
  cout << endl;
  P2.printPerson();
  cout << endl;

  Person P3;
  P3 = P1;
  P1.printPerson();
  cout << endl;
  P3.printPerson();
  cout << endl;

  P1.renamePerson("Liam", "White");

  P1.printPerson();
  cout << endl;
  P3.printPerson();
  cout << endl;

  exit(EXIT_SUCCESS);
}

输出:

Buddy Rich
Buddy Rich
Jay Roach
Buddy Rich
Jay Roach
Jay Roach
Liam White
Liam White

上面的代码仅明确定义了复制构造器,当将 P1 对象的内容赋值给 P3 对象时,会导致不正确的行为。请注意,第二次调用 P1.renamePerson 函数的第二次调用不应该修改 P3 对象的数据成员,但它修改了。解决方案是定义一个重载的赋值运算符,即复制赋值运算符。下一个代码片段实现了 Person 类的版本,该版本可以正确地复制赋值同一类的两个对象。但是请注意,复制赋值功能中的 if 语句可确保即使将对象赋值给自身,操作符也可以正常工作。

#include <iostream>
#include <string>
#include <utility>
#include <vector>

using std::cout;
using std::endl;
using std::string;
using std::vector;

class Person {
 public:
  Person() {
    name = new string;
    surname = new string;
  };
  Person(string n, string s) {
    name = new string(std::move(n));
    surname = new string(std::move(s));
  }
  Person(Person &p) {
    name = new string(*p.name);
    surname = new string(*p.surname);
  }

  ~Person() {
    delete name;
    delete surname;
  }

  Person &operator=(const Person &p) {
    if (this != &p) {
      *name = *(p.name);
      *surname = *(p.surname);
    }
    return *this;
  }

  void renamePerson(const string &n, const string &s) {
    name->assign(n);
    surname->assign(s);
  };

  void printPerson() { cout << *name << " " << *surname; }

 private:
  string *name;
  string *surname;
};

int main() {
  Person P1("Buddy", "Rich");
  Person P2 = P1;

  P1.printPerson();
  cout << endl;
  P2.printPerson();
  cout << endl;

  P1.renamePerson("Jay", "Roach");

  P1.printPerson();
  cout << endl;
  P2.printPerson();
  cout << endl;

  Person P3;
  P3 = P1;
  P1.printPerson();
  cout << endl;
  P3.printPerson();
  cout << endl;

  P1.renamePerson("Liam", "White");

  P1.printPerson();
  cout << endl;
  P3.printPerson();
  cout << endl;

  exit(EXIT_SUCCESS);
}

输出:

Buddy Rich
Buddy Rich
Jay Roach
Buddy Rich
Jay Roach
Jay Roach
Liam White
Jay Roach
作者: Jinku Hu
Jinku Hu avatar Jinku Hu avatar

DelftStack.com 创始人。Jinku 在机器人和汽车行业工作了8多年。他在自动测试、远程测试及从耐久性测试中创建报告时磨练了自己的编程技能。他拥有电气/电子工程背景,但他也扩展了自己的兴趣到嵌入式电子、嵌入式编程以及前端和后端编程。

LinkedIn Facebook

相关文章 - C++ Class