C++的一些基本知识:赋值运算符的重载

一、为什么要重载赋值运算符 "="?


  有时候希望赋值运算符两边的类型可以不匹配

 比如,把一个int类型变量赋值给一个Complex对象或把一个 char *类型的字符串赋值给一个字符串对象,此时就需要重载赋值运算符“=”

   赋值运算符“=”只能重载为成员函数

#include<iostream>
using namespace std;
class String {
private:
	char* str;
public:
	String() :str(new char[1]) { str[0] = 0; }
	const char* c_str() { return str; }
	String& operator=(const char* s);//重载赋值运算符
	~String() { delete[]str; }
};
String& String:: operator=(const char* s) {//赋值运算符号重载的类型是String &
	//重载”=“以使得obj ="hello"能够成立
	delete[] str;//
	str = new char[strlen(s) + 1];//+1为了存放起始位置0
	strcpy(str, s);
	return *this;

}
int main() {
	String s;
	s = "Good Luck ";//等价于 s.operator=("Good Luck");
	cout << s.c_str() << endl;
	//String s2="hello!"这条语句不注释掉就会出错
	s = "Shenzhou 8!";// 等价于 s.operator=("Shenzhou 8!);
	cout << s.c_str() << endl;
	return 0;
}

输出:

//String s2="hello!"这条语句不注释掉就会出错

因为这个等号不是赋值语句,而是初始化语句,初始化语句需要相应的构造函数,而且后面需要跟char *  的类型

二、浅拷贝与深拷贝

假如我们没有进行赋值符号的重载

声明 俩个String 的对象 s1=s2会引发一些问题,

String s1, s2;
s1 = "this";
s2 = "that";
s1=s2;

第一个问题,之前s1对象指向的地方没有办法被delete掉,成为内存垃圾

(1)如不定义自己的赋值运算符,那么S1=S2实际上导致S1.str和S2.str指向同一地方。

第二个问题,可能会造成俩次delete


(2)如果S1对象消亡,析构函数将释放S1.str指向的空间,则S2消亡时还要释放一次,不妥。

因为只能new 出来的空间只能 delete 一次; 

(3)另外,如果执行S1="other";会导致S2.str指向的地方被delete

因此要在 class String里添加成员函数,

String& String:: operator=(const char* s) {//赋值运算符号重载的类型是String &
	//重载”=“以使得obj ="hello"能够成立
	delete[] str;//
	str = new char[strlen(s) + 1];//+1为了存放起始位置0,, 为Str分配新的存储空间
	strcpy(str, s); //这样就不会导致s和str指向同一个位置,因为str是新new的一个空间
	return *this;

优化 1:

防止一个对象赋值给另外一个对象,而这个对象恰好又和这个赋值的对象是引用关系;

而我们的赋值重载函数第一句是delete;这样会导致自己删除自己的情况,我们需要改进

String s ;

String &x=s;

s=x;

改进:

String& String :: operator =(const String& s) {//赋值运算符号重载的类型是String &
	//重载”=“以使得obj ="hello"能够成立
	if (this == &s)  return *this;  //判断这个对象是否引用了自己
	delete[] str;//
	str = new char[strlen(s.str) + 1];//+1为了存放起始位置0
	strcpy(str, s.str);
	return *this;
}

 全部代码如下:

#define   _CRT_SECURE_NO_WARNINGS 
#include<iostream>
using namespace std;
class String {
private:
	char * str;
public:
	String() :str(new char[1]) { str[0] = 0; }
	const char* c_str() { return str; }
	String & operator=(const String& s);//重载赋值运算符
	String& operator=(const char *s);//重载赋值运算符
	~String() { delete[]str; }
};
String& String :: operator =(const String& s) {//赋值运算符号重载的类型是String &
	//重载”=“以使得obj ="hello"能够成立
	if (this == &s)  return *this;
	delete[] str;//
	str = new char[strlen(s.str) + 1];//+1为了存放起始位置0
	strcpy(str, s.str);
	return *this;
}
String& String:: operator=(const char* s) {//赋值运算符号重载的类型是String &
	//重载”=“以使得obj ="hello"能够成立
	delete[] str;//
	str = new char[strlen(s) + 1];//+1为了存放起始位置0
	strcpy(str, s);
	return *this;
}
int main() {
	/*String s;
	s = "Good Luck ";//等价于 s.operator=("Good Luck");
	cout << s.c_str() << endl;
	//String s2="hello!"这条语句不注释掉就会出错
	s = "Shenzhou 8!";// 等价于 s.operator=("Shenzhou 8!);
	cout << s.c_str() << endl;*/
	String s1, s2, s3, s4;
    String& s4 = s3;// 引用
	s4 = s3;
	s1 = "this";
	s2 = "that";
	s1 = s2;
	return 0;
}

优化二:我们还需要考虑编写复制构造函数

为 String类编写复制构造函数的时候,会面临和=同样的问题,用同样的方法处理。

String s1;

String s2(s1);//如果自己没写复制构造函数这会调用缺省构造函数,导致俩个对象指向同样的一片空间,从而引发跟上面一样的问题

改进:

String(const String& s) {
	str = new char[strlen(s.str) + 1]; //为str 重新开辟一个空间
	strcpy(str, s.str);
}

  • 5
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值