剑指offer--赋值运算符函数(精心分析,代码备注更利于分析问题)

题目:如下为类型CMyString的声明,请为该类型添加赋值运算符函数

class CMyString
{
public:
    CMyString(char* p_Data = NULL); 
    CMyString(const CMyString& str);
    ~CMyString(void);
private:
    char* m_pData;
};

1.题目分析

1.1 那些c++类中的函数

一个c++类中常见的有构造函数、拷贝构造、赋值运算符重载、析构,其中拷贝构造、赋值运算符重载默认使用编译器浅拷贝(值拷贝,简单的赋值);

构造函数和析构函数:创建对象时,初始化赋值用;编译器自动调用;编译器会提供,但是为空实现

拷贝构造:什么时候会用到拷贝构造?三种情况:用一个创建完的对象初始化新对象person p1(p2)、值传递方式给函数传参、值传递方式返回局部对象;什么时候需要深拷贝呢?当属性有在堆区开辟的,即类中含指针、new操作;此时可能造成多个指针指向同块内存,在析构时重复释放;

运算符重载:对已有的运算符重新定义,赋予新功能;本题中赋值运算符函数类内含指针,涉及到深拷贝;

1.2 标题类和对象中直接赋值对象p2 = p1行不行?

情况1:如果类中没有开辟在堆区的成员或属性(不用new,无指针),可以直接赋值,如下程序运行通过;

class person{
public:
	person( int age){
			m_age =  age;
		}
	int m_age;
};
void test(){
	person p(18);
	person p2(20);
	person p3(30);
	p3 =p2 = p;  
	cout<<"年龄= "<<p.m_age<<endl;  //18
	cout<<"年龄= "<<p2.m_age<<endl; //18
	cout<<"年龄= "<<p3.m_age<<endl; //18
}

情况2:如果类中开辟在堆区的成员或属性,不可以直接赋值,因为在创建不同对象p1、p2时,在堆区会开辟两块新空间,简单的赋值p1 = p2会造成两个指针指向同块内存,在析构时重复释放;

#1.2.1 如何进行深拷贝

针对情况 2,需要深拷贝来解决问题,步骤:
1.首先判断p2 在堆区是否有数据,若有先释放;
2.其次new一个新空间;这样使用 = 时才会避免内存重复释放;
3.扩展:使用连续赋值 p3 = p2 = p1;要注意重载运算符函数的返回值;
程序如下:

class person{
public:
	person( int age  ){
	m_age = new int( age); //new int 返回int *			
		}
	//赋值运算重载 operator=
	//连续赋值需要注意返回值,要用引用才能返回真正的自己;不用引用相当按照自身,调用拷贝构造函数(编译器自动给的值拷贝),创建一个新的副本
	//参数传入用引用传递,如果用值传递相当于传入复制品,即需要调用一次复制构造函数,无益
	person& operator= (person &p){
		
		//编译器浅拷贝
		// m_age =  p.m_age;
		//怎么进行深拷贝,首先p2(20)创建时堆区上已经有数据了;先判断有无数据,释放干净
		if(m_age != nullptr){
			delete m_age;
			m_age = nullptr;		
		}
		//其次,深拷贝,创建块堆区
		m_age = new int(*p.m_age);
		//返回对象本身,用this指针;解引用,就是对象本身
		return *this;	
	}
	~person(){
		if(m_age != nullptr){
			delete m_age;
			m_age =  nullptr;
		}	
	}	
	int *m_age; //加*,就要开辟到堆区
};

void test(){
	person p(18);
	person p2(20);
	person p3(30);
	p3 =p2 = p;      //赋值运算符需要重载,进行深拷贝解决浅拷贝问题;
	cout<<"年龄= "<<*p.m_age<<endl;
	cout<<"年龄= "<<*p2.m_age<<endl;
	cout<<"年龄= "<<*p3.m_age<<endl;	
}

2.回归本题


//返回值 
//函数书写 
//传入参数
CMyString& CMyString:: operator = (const CMyString &str){	
	if(this == &str) return *this; 

	if(m_pData != nullptr){
		delete[]m_pData;
		m_pData = nullptr;
	}

	m_pData = new char [strlen(str.m_pData)+1];
	copystr(m_pData,str.m_pData);

	return *this;
}

如有错误,欢迎指正*****

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值