1 目的:希望赋值运算符两边的类型可以不匹配
eg:将int类型变量赋值给一个Complex对象;或者吧一个char*类型的字符串赋值给一个字符串对象。
2 赋值运算符‘=’只能重载为成员函数
3 eg:(见本工程fuzhichongzai.cpp)
/**
* 赋值运算符‘=’重载例子
* */
#include <iostream>
#include <cstring>
using namespace std;
class String{
private:
char* str; // 私有成员变量 str是一个指针,用来指向动态分配的存储空间,字符串就放在动态分配的存储空间
public:
// 构造函数 new一个字符数组,只有一个元素,使得指针str指向new出来的存储空间 相当于 char* str = new char[1];
String() //:str(new char[1])
{
str = new char[1];
str[0] = 0; // 初始化后str指向一个空字符串
cout << "调用无参构造函数" << endl;
}
const char* c_str()
{
return str;
}
// 对赋值运算符进行重载,接收的参数是 const char* 返回值为String&
String& operator=(const char* s);
// 析构函数
~String()
{
cout << "调用析构函数" << endl;
delete[] str;
}
};
String& String::operator= (const char *a) {
// 重载‘=’使得obj = "hello"能够成立 obj是String对象,
delete[] str; // 删除String对象中为str成员变量分配的内存空间
// 为str重新分配存储空间 加1的目的 存放\0
str = new char[strlen(a) + 1];
// 将a指针指向的内容copy到str指针指向的内容,此时String对象中str指向的内容就是a指向的内容
strcpy(str, a);
return *this; // 返回这个已修改str指向内容的String对象的引用
}
int main()
{
String s;
s = "Good Luck,"; // 等价于 s.operator= ("Good Luck,");
cout << s.c_str() << endl;
// String s2 = "hello!"; //这条语句要是不注释就会出错 原因,该语句是初始化语句而不是赋值语句,初始化语句的话,要求该函数用构造函数初始化,构造函数参数必须是char 或const char型
s = "Shenzhou 8!"; // 等价于s.operator = ("Shenzhou 8!");
cout << s.c_str() << endl;
return 0;
}
4 浅拷贝和深拷贝
在3中的例子中,希望执行以下语句
String S1, S2;
S1 = "this";
S2 = "that";
S1 = S2; // 希望达到的目的是S1里放置的字符串和S2中放置的字符串一样。
对于S1 = S2;这条语句,如果使用的是原生的等号,则会产生问题
问题如下
S1 str ------> this\0 // 执行S1 = "this"; S1中str指向this\0
S2 str ------> that\0 // 执行S2 = "that"; S2中str指向that\0
// 执行 S1 = S2; 此时的等号没有经过重载
// 则没有指针指向 this\0 存储空间,该空间没有机会被delete掉,造成内存垃圾
this\0
// S1和S2中str都指向 that\0 存储空间
// 如果S1对象消亡,析构函数将释放S1.str指向的空间,则S2消亡时还要释放一次,不妥。
S1 str ------>
that\0
S2 str ------>
// 另外,如果再执行S1 = "other"; 会导致S2.str指向的地方被delete
因此,解决以上问题的方法是在class String 里面添加成员函数 String& operator= (cosnt String& s);见3中例子。
还有需要改进的地方:
如下语句: String s; s = "Hello"; s = s; 就会出现错误。
改进方法:
String& operator= (const String& s){
// 判断当前对象与s是否为同一个 this指针代表的是个地址
if(this == &s)
return *this;
delete[] str;
str = new char[strlen(s.str) + 1];
strcpy(str, s.str);
return *this;
}
对operator=返回值的讨论
void好不好?
String好不好?
为啥是String&?
原因:对运算符进行重载的时候,好的风格应该尽量保留运算符原本的特性
如果重载运算符返回void,由于b = c返回void a = void错误,因此不能维持连等特性 a = b = c
如果重载运算符返回String ,考虑(a = b) = c, 由于在C++中,赋值运算符的返回值是等号左边那个变量的引用,所以(a = b)的返回值是a的引用 将a的引用付给c,效果是a的值和c的值一样,跟b没有关系。
考虑: a = b = c; 等价于 a.operator=(b.operator=(c));
和(a = b) = c; 会修改a的值 等价于 (a.operator=(b)).operator=(c);
在C++中,赋值运算符的返回值是等号左边那个变量的引用
目前String类还有什么问题?
为String类编写复制构造函数时候,会面临和不重载的=同样的问题,用同样的方法处理
String(String& s)
{
str = new char[strlen(s.str) + 1];
strcpy(str, s.str);
}
来源:CSDN
作者:longbatianxia1
链接:https://blog.csdn.net/longbatianxia1/article/details/104158897