赋值运算符重载
- 类的默认函数
- 拷贝构造函数和赋值运算符
- 重载赋值运算符
- 相关注意事项
类的默认函数
一个类至少有4个默认函数:
- 默认构造函数
- 拷贝构造函数
- 析构函数
- 赋值运算符重载函数
拷贝构造函数和赋值运算符
- 拷贝构造函数是在创建类的时候调用的,之前类并不存在。
- 赋值运算符是在两个类均存在的情况下,把一个类的属性全部赋值给另外一个类。
- 默认的拷贝构造函数和默认的赋值运算符在对象有堆区内存时,因为默认的均是浅拷贝,所以均会存在内存重复释放的问题。
重载赋值运算符
- 语法:类名& operator=(const 类名& ref_h)
相关注意事项
- 在对象的属性有在堆区开辟内存的情况下,不管是拷贝构造函数还是赋值运算符,都需要进行自定义。
- 使用new在堆区重新开辟空间,避免重复释放。
-
浅拷贝
-
深拷贝
code:#include <iostream>using namespace std;class Horse{private:int *m_age;public:Horse(int ref_age){m_age = new int(ref_age);}Horse(const Horse& ref_h){m_age = new int(*ref_h.m_age);//m_age = ref_h.m_age; //默认的构造函数是这种实现方式,简单的赋值操作,在存在指针时,只是将指针简单赋值,指针指向的堆区空间并不进行拷贝。cout << "拷贝, " << m_age << ", " << ref_h.m_age << ", age: " << * ref_h.m_age << endl;}Horse& operator=(const Horse& ref_h) // 返回自身的引用,链式编程,实现连等操作{if (this == &ref_h) // 如果是自身赋值,如h1=h1,直接返回cout << "自身赋值" << endl;return *this;// 如果对象已经有开辟了空间,先进行释放if (m_age != NULL){delete m_age;m_age = NULL;}//m_age = ref_h.m_age; //默认的是这种实现方式,简单的赋值操作,在存在指针时,只是将指针简单赋值,指针指向的堆区空间并不进行拷贝。m_age = new int(*ref_h.m_age); // 深拷贝cout << "=," << m_age << ", " << ref_h.m_age << ", age: " << * ref_h.m_age << endl;return *this;}~Horse(){if (m_age != NULL){cout << "析构:" << m_age << endl;delete m_age;m_age = NULL;}}void show_info(){cout << "age: " << * m_age << endl;}};// 对拷贝构造函数的测试void test01(){Horse h1(0);h1.show_info();Horse h2(h1);h2.show_info();}// 对=操作符的测试void test02(){Horse h1(88);Horse h2(2);Horse h3(5);h3 = h2 = h1;h1.show_info();h2.show_info();h3.show_info();}void main(){test01();cout << "************************" << endl;test02();system("pause");}
result:age: 0拷贝, 0000024C16116510, 0000024C16116A50, age: 0age: 0析构:0000024C16116510析构:0000024C16116A50************************=,0000024C16116150, 0000024C16116750, age: 88=,0000024C161164D0, 0000024C16116150, age: 88age: 88age: 88age: 88析构:0000024C161164D0析构:0000024C16116150析构:0000024C16116750
- 注意在赋值运算符重载函数中,先判断是否在堆区有内存,有的话先释放,再重新开辟。