剑指offer_Q01赋值运算符函数

赋值运算符“=”编程


类为具有指针存储char字符串的一个自定义CMyStr类。

CMyString 类定义

#include <string.h>

class CMyString
{
private:
	char* m_pData;

public:
	CMyString(char* pData = nullptr);
	CMyString(const CMyString& MyStr);
	~CMyString(void);

	CMyString& operator=(const CMyString& Str);
};

CMyString::CMyString(char* pData)
{
	if (pData == nullptr) return;
	size_t len = strlen(pData) + 1;
	m_pData = new char[len];//记得要加1,放置'\0'
	strcpy_s(m_pData, len, pData);
}

inline CMyString::CMyString(const CMyString & MyStr)
{
	size_t len = strlen(MyStr.m_pData) + 1;
	m_pData = new char[strlen(MyStr.m_pData)+1];//记得要加1,放置'\0'
	strcpy_s(m_pData, len, MyStr.m_pData);
}

inline CMyString::~CMyString(void)
{
	delete[]m_pData;
}

第一种实现

四个关键点

  1. 返回值为本身的引用,便于连续等于,如 a=b=c,如果返回值不是引用,则无法连等。
  2. 形参为const引用,避免因为值传递调用复制构造函数
  3. 判断传入的对象是否为自身,如果是则跳过if (&Str == this)
  4. 如果存储的数据为指针,则要将已有空间析构

代码

inline CMyString & CMyString::operator=(const CMyString & Str)
{
	if (&Str == this) //判断是否是自身
		return *this;
	delete[]m_pData;
	m_pData = nullptr;

	m_pData = new char[strlen(Str.m_pData)+1];//记得要加1,放置'\0'
	strcpy(m_pData, Str.m_pData);
	return *this;
}

第二种实现

考虑更好的内存稳定型和异常处理

  1. 使用复制构造函数
  2. 以传入的形参为基础,调用复制构造函数创建临时对象
  3. 将临时对象与当前对象交换指针
  4. 离开函数时,临时对象析构,自动销毁原对象的空间

代码

利用临时对象和 拷贝构造函数,临时对象离开函数后自动析构

inline CMyString & CMyString::operator=(const CMyString & Str)
{
	if (&Str != this)//判断是否是自身
	{
		CMyString tmpStr(Str);

		char* pTmp = tmpStr.m_pData;
		tmpStr.m_pData = m_pData;
		m_pData = pTmp;
		cout << "execute copy operator" << endl;
	}
	return *this;
}

拷贝构造函数和赋值运算符的区别

参考

拷贝构造函数:使用传入对象的值生成一个新的对象
赋值运算符:将对象的值赋值给一个已经存在的实例

调用的是拷贝构造函数还是赋值运算符,主要是看是否有新的对象实例产生,如果产生了新的对象实例,那调用的就是拷贝构造函数;如果没有,那就是对已有的对象赋值,调用的是赋值运算符。

调用拷贝构造函数主要有以下场景:

1. 对象作为函数的参数,以值传递的方式传给函数。
  2. 对象作为函数的返回值,以值的方式从函数返回。
  3. 使用一个对象给另一个对象初始化。

!!需注意**等于号=**并不等于一定使用赋值运算符:

Person p;
Person p1 = p;    // 此时虽然是等于号,但是因为p1是新对象,所以仍然是调用的 拷贝构造函数

测试

#include <iostream>
using namespace std;

#include "MyString.h"

void test()
{
	CMyString s1("my string hh!");
	CMyString s2(s1);//复制构造函数
	CMyString s3;
	s3 = s2; //赋值运算符
	s3 = s3; //函数内跳过赋值,因为是本身
	CMyString s4("New things!");
	CMyString s5 = s3 = s4; //复制构造函数 +  赋值运算符
	CMyString s6 = s5; //复制构造函数
}

int main()
{
	test();

	system("pause");
	return 0;
}
CMyString s5 = s3 = s4; //复制构造函数 +  赋值运算符
CMyString s6 = s5; //复制构造函数

}

int main()
{
test();

扫描二维码关注公众号,回复: 10650787 查看本文章
system("pause");
return 0;

}


发布了48 篇原创文章 · 获赞 10 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/mhywoniu/article/details/104885349