运算符重载———赋值运算符的重载

目的:

有时候希望赋值运算符两边的类型可以不匹配,比如,把一个int类型变量赋值给一个Complex对象,或把一个 char * 类型的字符串赋值给一个字符串对象,此时就需要重载赋值运算符“=”。

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

赋值运算符重载实例示例:

#include <iostream>
#include <string.h>
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 & String::operator = (const char * s) 
{ //重载“=”以使得 obj = “hello”能够成立
	delete [] str;
	
	str = new char[strlen(s)+1];
	
	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;
}
/*
输出结果:
Good Luck,
Shenzhou 8!
*/

浅拷贝和深拷贝:

String S1, S2;  //S1,S2为String类的对象。
S1 =this;   //已经定义了 这种赋值的重载(如上面的程序)
S2 = “that”;
S1 = S2;      //将调用String类的默认复制构造函数。

浅拷贝:

导致“指针悬挂“问题
如果我们没有两个对象间,定义赋值运算符的重载,执行S1=S2;会导致许多隐藏的问题。(浅拷贝)
下面是我们的执行过程(没有定义赋值运算符);

1:对两个对象进行

在这里插入图片描述
2:执行S1 = S2后。
在这里插入图片描述

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

导致问题:

  • 如果S1对象消亡,析构函数将释放 S1.str指向的空间,则S2消亡时还要释放一次,不妥。
  • 如果执行 S1 = “other”;会导致S2.str指向的地方被delete

解决方法:在class String里添加成员函数:。

深拷贝:

为了解决浅拷贝出现的错误,必须显式地定义一个自己的赋值运算符,使之不但赋值数据成员,而且为对象 p1 和 p2 分配了各自的内存空间,这就是深拷贝。

String & operator = (const String & s) {
	delete [] str;
	str = new char[strlen( s.str)+1];
	strcpy( str,s.str);
	return * this;
}

修改示例:

#include <iostream>
#include <string.h> 

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){
			delete [] str;
			str = new char[strlen(s)+1];
			strcpy( str, s);
			return * this;
		}

		~String( ) { delete [] str; }
		
		String & operator = (const String & s) {
			delete [] str;
			str = new char[strlen( s.str)+1];
			strcpy( str,s.str);
			return * this;
		}
};
int main()
{
	String S1, S2;
	S1 = "this";
	S2 = "that";
	cout << S1.c_str() << endl;
	cout << S2.c_str() << endl;
	S1 = S2;
	cout << S1.c_str() << endl;
	cout << S2.c_str() << endl;
	return 0;
}
/*
输出结果:
this
that
that
that
*/

讨论:对 operator = 返回值类型的讨论

void 好不好?String 好不好? 为什么是 String &
1:对运算符进行重载的时候,好的风格是应该尽量保留运算符原本的特性

String & operator = (const char * s){
		delete [] str;
		str = new char[strlen(s)+1];
		strcpy( str, s);
		return * this;
	}

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

某些时候会自动调用复制构造函数会产生一些临时对象,这些对象在析构函数中被释放时会空间,那么就可能导致指针悬挂问题。解决方法:重写复制构造函数

String( String & s) 
{
	str = new char[strlen(s.str)+1];
	strcpy(str,s.str);
}

猜你喜欢

转载自blog.csdn.net/qq_44923545/article/details/106047603
今日推荐