[c++]赋值运算符重载
目录
一、运算符重载
二、赋值运算符重载
1、赋值运算符重载格式
2、赋值运算符重载深浅拷贝问题
3、赋值运算符只能重载成类成员函数
4、拷贝构造与赋值运算符重载区别
三、总结
一、运算符重载
运算符重载实际上是为了让自定义类型能够像内置类型一样进行已有的运算符运算。简单点理解就是让自己定义的类能够实现+或者+=以及比大小等等一些数据操作运算,编译器不支持自定义类型的这些操作,而支持内置类型,所以根据自己的需求来决定实现哪些运算符重载。
运算符重载是具有特殊函数名的函数,与普通函数类似,具有返回值类型,函数名以及参数列表。
函数名是关键字operator加上需要重载的运算符符号。例如operator+、operator+=.
函数原型:返回值类型 operator操作数 (参数列表)
注意事项
- 不能通过连接其他符号来创建新的操作符:比如operator@
- 重载操作符必须有一个类类型参数-例如日期类+天数
- 用于内置类型的运算符,其含义不能改变,例如:内置的整型+,不 能改变其含义
- 作为类成员函数重载时,其形参看起来比操作数数目少1,因为成员函数的第一个参数为隐
- 藏的this
- .* :: sizeof ?: . 注意以上5个运算符不能重载。这个经常在笔试选择题中出现。
//代码示例
class Date
{
public://全缺省构造函数Date(int year = 2025, int month = 11, int day = 15){_year = year;_month = month;_day = day;}////实现 == 运算符重载bool operator==(const Date& d){return _year == d._year &&_month == d._month &&_day == d._day;}//实现 == 运算符重载 重载成全局时用友元解决类内私有变量访问//friend bool operator==(const Date& d1, const Date& d2);private:int _year;int _month;int _day;
};int main()
{Date d1;Date d2(2025, 11, 16);cout << (d1 == d2) << endl;
}//实现 == 运算符重载 重载成全局时用友元解决类内私有变量访问
//bool operator==(const Date& d1, const Date& d2)
//{
// return d1._year == d2._year &&
// d1._month == d2._month &&
// d1._day == d2._day;
//} 二、赋值运算符重载
1、赋值运算符重载格式
- 参数类型:const T&,传递引用可以提高传参效率
- 返回值类型:T&,返回引用可以提高返回的效率,有返回值目的是为了支持连续赋值
- 检测是否自己给自己赋值
- 返回*this :要复合连续赋值的含义
class Date
{
public://全缺省构造函数Date(int year = 2025, int month = 11, int day = 15){_year = year;_month = month;_day = day;}void print(){cout << _year << "-" << _month << "-" << _day << endl;;}////实现 == 运算符重载bool operator==(const Date& d){return _year == d._year &&_month == d._month &&_day == d._day;}//实现 == 运算符重载 重载成全局时用友元解决类内私有变量访问//friend bool operator==(const date& d1, const date& d2);//简单版本//void operator=(const Date& d)//{// _year = d._year;// _month = d._month;// _day = d._day;//}//tip1:为了让赋值运算符能够符合内置类型的连续赋值,同时*this出了作用域还在,返回值类型可以加上引用//如果临时对象出了作用域不在,则不能用引用返回,只能返回其拷贝//例如:希望实现连续赋值 d3=d2=d1,d1赋值给d2,d2也就是*this出了作用域还在,那么可以用Date& 接收 ,继续赋值给d3// 否则不能用Date&接收 只能用Date接收(会调用拷贝构造)//tip2:避免出现自己给自己赋值的情况出现,可以在函数做判断Date& operator=(const Date& d){if (this != &d){_year = d._year;_month = d._month;_day = d._day;}return *this;}private:int _year;int _month;int _day;
};int main()
{Date d1;Date d2(2025, 11, 16);cout << "赋值前d1=" << endl;d1.print();cout << "赋值前d2=" << endl;d2.print();d2 = d1;cout << "赋值后d1=" << endl;d1.print();cout << "赋值后d2=" << endl;d2.print();}
//运行结果
赋值前d1=
2025-11-15
赋值前d2=
2025-11-16
赋值后d1=
2025-11-15
赋值后d2=
2025-11-15
2、赋值运算符重载深浅拷贝问题
如果没有显示写赋值运算符重载,编译器生成默认运算符重载完成浅拷贝(与拷贝构造函数类似),内置类型完成浅拷贝,自定义类型调用自己的赋值运算符重载。如果对象有申请资源,那么要实现深拷贝来解决问题,避免使用浅拷贝。这个问题可以参考该篇博客内容。[C++]拷贝构造函数使用规则以及注意事项
3、赋值运算符只能重载成类成员函数
赋值运算符重载不能重载成全局函数,会与类中默认生成的赋值运算符冲突。但并不是说不能写在类外,而是可以在类内声明,类外定义。

class Date
{
public://全缺省构造函数Date(int year = 2025, int month = 11, int day = 15){_year = year;_month = month;_day = day;}//赋值运算符重载//类内声明Date& operator=(const Date& d);//friend Date& operator=(const Date& d1, const Date& d2);//errorprivate:int _year;int _month;int _day;
};//类外定义
Date& Date::operator=(const Date& d)
{if (this != &d){_year = d._year;_month = d._month;_day = d._day;}return *this;
}
4、拷贝构造与赋值运算符重载区别
拷贝构造是用已存在的对象去创建一个新对象。
//示例:Date d2(d1)中,d2是新对象,d1是已经存在的对象。Date d1;Date d2(d1);
赋值运算符重载是用一个已经存在的对象去赋值给另一个存在的对象。
//示例:d1是已经存在的对象,d2也是已经存在的对象
Date d1(2025,11,15);
Date d2(2025,11,16);
d2=d1;
三、总结

tp1、.赋值运算符重载参数是const Date&类类型的引用,第一个参数是隐含的this指针
tip2、避免出现自己给自己赋值的情况出现,可以在函数内做判断
tip3、为了让赋值运算符能够符合内置类型的连续赋值,同时*this出了作用域还在,返回值类型可以加上引用
如果临时对象出了作用域不在,则不能用引用返回,只能返回其拷贝
例如:希望实现连续赋值d3=d2=d1,d1赋值给d2,d2也就是*this出了作用域还在,那么可以用Date&接收,继续赋值给d3,否则不能用Date&接收只能用Date接收(会调用拷贝构造)
tip4、赋值运算符重载涉及深浅拷贝问题,如果没有显示写赋值运算符重载,编译器生成默认运算符重载完成浅拷贝(与拷贝构造函数类似),内置类型完成浅拷贝,自定义类型调用自己的赋值运算符重载。如果对象有申请资源,那么要实现深拷贝来解决问题,避免使用浅拷贝。
tip5、赋值运算符只能重载成类成员函数,赋值运算符重载不能重载成全局函数,会与类中默认生成的赋值运算符冲突。可以在类内声明,类外定义。
tip6、拷贝构造函数和赋值运算符重载区别
拷贝构造是用已存在的对象去创建一个新对象。示例:Date d2(d1)中,d2是新对象,d1是已经存在的对象。
赋值运算符重载是用一个已经存在的对象去赋值给另一个存在的对象,示例:d2=d1;d1是已经存在的对象,d2也是已经存在的对象
