赋值运算符重载
- 类的默认函数
- 拷贝构造函数和赋值运算符
- 重载赋值运算符
- 相关注意事项
类的默认函数
一个类至少有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: 0
age: 0
析构:0000024C16116510
析构:0000024C16116A50
************************
=,0000024C16116150, 0000024C16116750, age: 88
=,0000024C161164D0, 0000024C16116150, age: 88
age: 88
age: 88
age: 88
析构:0000024C161164D0
析构:0000024C16116150
析构:0000024C16116750
- 注意在赋值运算符重载函数中,先判断是否在堆区有内存,有的话先释放,再重新开辟。