个人主页:Jason_from_China-CSDN博客
所属栏目:C++系统性学习_Jason_from_China的博客-CSDN博客
所属栏目:C++知识点的补充_Jason_from_China的博客-CSDN博客
概念概述
赋值运算符重载的特点:
- 成员函数:赋值运算符重载必须定义为类的成员函数。
- 参数:建议将参数声明为
const
类型的类引用,以避免不必要的拷贝。- 返回值:应有返回值,且建议为当前类类型的引用,这样可以支持连续赋值操作,并提高效率。
编译器自动生成的赋值运算符:
- 如果没有显式实现赋值运算符重载,编译器会提供一个默认实现。
- 默认赋值运算符对内置类型成员变量执行值拷贝或浅拷贝。
- 对自定义类型成员变量,会调用其赋值运算符重载函数。
特定情况下的赋值运算符重载:
- 对于像
Date
这样只有内置类型成员的类,编译器自动生成的赋值运算符通常足够使用。- 对于像
Stack
这样包含指向资源的成员的类,需要自定义赋值运算符以实现深拷贝。- 对于像
MyQueue
这样包含自定义类型成员的类,如果这些成员的赋值运算符已经正确实现,通常不需要为MyQueue
显式实现赋值运算符重载。额外技巧:
- 如果一个类显式实现了析构函数并释放资源,通常也需要显式实现赋值运算符重载,以确保资源被正确管理。
赋值运算符重载的使用以及注意事项
1,有返回值,建议写成const类类型的引用。因为C++规定类类型的传值传参,会调用拷贝构造,传递引用会减少拷贝(提高效率)
2,连续赋值的返回值
d3=d1;
返回值是d3,所以我们写代码的时候,要注意返回值,很可能是this
第一次赋值
第二次赋值
3,当返回的节点是d2,如何实现返回d2(用this,this本身指向的就是返回值)(这里注意:有返回值就支持连续赋值,但是返回的时候,需要注意)
注意:这里返回是可以用引用返回的,因为赋值运算符重载是两个已有的对象。出去作用域是依旧存在的(这里代码是传值返回,会增加拷贝)
4,这里还有一个问题,就是d1可以复制給給d1,所以为了防止自己給自己赋值 ,会进行判断
代码实现
//.h文件 //运算符重载,比较大小的实现,不在类里面实现 class Date { public:Date(int year = 1000, int month = 1, int day = 1);//声明给,定义不给Date(Date& d);void print();bool operator<(const Date& d);//比较日期大小(重载为成员函数)Date& operator++();Date& operator++(int);//赋值运算符重载(这里是可以加上const的,因为这里改变的是this不是d)Date& operator=(const Date& d);private:int _year;int _month;int _day; };//.cpp实现文件 #include"类和对象的通篇实现.h" //构造函数的实现(全缺省构造函数的实现) Date::Date(int year, int month, int day) {_year = year;_month = month;_day = day; } //拷贝构造的实现 Date::Date(Date& d) {_year = d._year;_month = d._month;_day = d._day; } //打印函数的实现 void Date::print() {cout << _year << "/" << _month << "/" << _day << endl; }//日期类的比较日期的大小,this-> < d.year 此时返回 bool Date::operator<(const Date& d) {//比较年if (this->_year < d._year){return true;}else{if (this->_year == d._year && this->_month < d._month)//比较月{return true;}else if (this->_year == d._year && this->_month < d._month && this->_day < d._day)//比较日{return true;}}return false; }//前置++ Date& Date::operator++() {this->_day += 1;return *this; } //后置++ Date& Date::operator++(int) {Date tmp = *this;this->_day += 1;return tmp; }//赋值运算符重载(这里是可以加上const的,因为这里改变的是this不是d) Date& Date::operator=(const Date& d) {//地址不一样才进行赋值if (this != &d){_year = d._year;_month = d._month;_day = d._day;}return *this; }//.cpp测试文件 //运算符重载,比较大小 int main() {//构造和拷贝构造函数的使用Date d1(1000, 2, 1);d1.print();Date d2 = d1;d2.print();//比较年月日Date d3(999, 1, 1);bool ret1 = d1.operator<(d3);cout << ret1 << endl;Date d4(1100, 1, 1);bool ret2 = d1.operator<(d4);cout << ret2 << endl;//前置++和后置++cout << "前置++和后置++" << endl;d4.print();//1100 ,1,1d4.operator++();d4.print();Date ret = d4.operator++(1);ret.print();d4.print();//赋值运算符重载 cout << "赋值运算符重载" << endl;Date d5(1, 1, 1);d5.print();d5 = d4;//这样写也是对的//d5.operator=(d4);//这样写也是对的d5.print();return 0; }
赋值运算符重载什么时候需要自己实现
注意:默认的赋值运算符重载也会完成浅拷贝(有资源,就需要自己完成赋值运算符重载)
1,内置类型不指向什么资源,不需要自己实现,编译器自动生成的就可以实现
2,栈和深拷贝,都需要自己写,和拷贝构造非常相似
3,如果写了析构函数,那么赋值运算符重载就需要自己写
几个函数之间进行对比
1、构造一般都需要自己写,自己传参定义初始化
2、析构,构造时有资源申请(如malloc或者fopen)等,就需要显示写析构函数
3、拷贝构造和赋值重载,显示写了析构,内部管理资源,就需要显示实现深拷贝