1.拷贝构造函数 vs 赋值运算符重载
当我们定义一个类时,会显式或隐式地指定了此类的对象在拷贝、赋值和销毁时做什么。一个类通过定义三种特殊的成员函数来控制这些操作,分别是拷贝构造函数、赋值运算符和析构函数。拷贝控制操作:拷贝构造函数被用来以同类型对象初始化自我对象,赋值运算符重载被用来从另一个同类型对象中拷贝其值到自我对象中。析构函数定义了此类型的对象销毁时做什么。
注意:如果一个新对象被定义,一定会有个构造函数被调用,不可能调用赋值运算符重载。如果没有新的对象被定义,就不会有构造函数被调用,那么就会调用赋值运算符重载。
2.三/五法则
由于拷贝控制操作是由三个特殊的成员函数来完成的,所以称此为“C++三法则”。在较新的C++11标准中,为了支持移动语义,又增加了移动构造函数和移动赋值运算符,这样共有五个特殊的成员函数,所以又称为“C++五法则”。也就是说,“三法则”是针对较旧的C++89标准说的,“五法则”是针对较新的C++11标准说的。为了统一称呼,人们把它称为“C++ 三/五法则”。
3.实例演示
1#include <iostream> 2#include <cstdlib> 3#include <cstring> 4 5using namespace std; 6 7 8class Array 9{ 10public: 11 Array(int len); 12 Array(const Array &arr); // 拷贝构造函数 13 ~Array(); 14 15public: 16 int operator[](int i) const { return m_p[i]; } // 以常成员函数(只读)形式重载[]运算符 17 int &operator[](int i) { return m_p[i]; } // 获取元素(写入) 18 Array &operator=(const Array &arr); // 重载赋值运算符!!!operator=()的形参类型是const Array &,这样不但能够避免在传参时调用拷贝构造函数,还能够同时接收const类型和非const类型的实参 19 int length() const { return m_len; } 20 void show(); 21 22private: 23 int m_len; 24 int *m_p; 25}; 26 27// 构造函数的定义 28Array::Array(int len) : m_len(len) 29{ 30 m_p = (int *)calloc(len, sizeof(int)); // 动态分配内存空间,使得指针m_p指向新分配的内存空间 31} 32// 拷贝构造函数的定义 33Array::Array(const Array &arr) 34{ 35 this->m_len = arr.m_len; 36 this->m_p = (int *)calloc(this->m_len, sizeof(int)); 37 memcpy(this->m_p, arr.m_p, m_len * sizeof(int)); 38} 39 40Array::~Array() 41{ 42 free(m_p); 43} 44// 重载赋值运算符 45Array &Array::operator=(const Array &arr) 46{ // operator=()的返回值类型是Array &,这样不但能够避免在返回数据时调用拷贝构造函数,还能够达到连续赋值的目的 47 if (this != &arr) 48 { // 判断是否是给同一个对象赋值 49 this->m_len = arr.m_len; 50 free(this->m_p); 51 this->m_p = (int *)calloc(this->m_len, sizeof(int)); 52 memcpy(this->m_p, arr.m_p, m_len * sizeof(int)); 53 } 54 return *this; // 表示返回当前对象 55} 56 57// 普通成员函数的定义 58void Array::show() 59{ 60 cout << "我是普通成员函数....\n"; 61} 62 63// 打印数组元素 64void printArray(const Array &arr) 65{ 66 int len = arr.length(); 67 for (int i = 0; i < len; i++) 68 { 69 if (i == len - 1) 70 { 71 cout << arr[i] << endl; 72 } 73 else 74 { 75 cout << arr[i] << ", "; 76 } 77 } 78} 79 80int main() 81{ 82 Array arr1(10); 83 for (int i = 0; i < 10; i++) 84 { 85 arr1[i] = i; 86 } 87 cout << "arr1:"; 88 printArray(arr1); 89 90 Array arr2(5); 91 for (int i = 0; i < 5; i++) 92 { 93 arr2[i] = i; 94 } 95 cout << "arr2:"; 96 printArray(arr2); 97 cout << "------------------------------------\n"; 98 arr2 = arr1; // 调用operator=() 99 cout << "将arr1赋值给arr2:"; 100 printArray(arr2); 101 arr2[3] = 234; // 修改arr2的数据不会影响arr1,如果把operator=()注释掉,修改arr2的值就会影响arr1的值 102 arr2[7] = 920; 103 cout << "修改arr2的值不会影响arr1:"; 104 printArray(arr1); 105 return 0; 106}
4.参考资料
[1] https://www.cnblogs.com/yongdaimi/p/7121151.html