类中赋值运算符重载函数

时间:2022-10-13 19:08:37

声明一个字符串类,为这个类型添加赋值运算符

class MyString
{
public:

	//构造函数
    MyString(char* pData = NULL);

	//构造函数
    MyString(const MyString& str);

	//析构函数
    ~MyString(void);
	
	//赋值运算符
    MyString& operator=(const MyString& str);
  
private:
    char* m_pData;
};

该字符串类中只有两个构造函数,一个析构,一个赋值运算符的重载,着重来说赋值运算符的重载,重载之前将构造函数和析构函数实现了

MyString::MyString(char *pData)
{
    if(pData == NULL)
    {
        m_pData = new char[1];
        m_pData[0] = '\0';
    }
    else
    {
        m_pData = new char[strlen(pData) + 1];
        strcpy(m_pData, pData);
    }
}

MyString::MyString(const MyString &str)
{
    m_pData = new char[strlen(str.m_pData) + 1];
    strcpy(m_pData, str.m_pData);
}

MyString::~MyString()
{
    delete[] m_pData;
}


关于赋值运算符的重载,上一张图

类中赋值运算符重载函数

S1 = S2 ,S1传给第一个参数,S2传给第二个参数,赋值自然顺理成章,以下是代码:

MyString& MyString::operator=(const MyString& str)
{
	if (this != &str)   //如果相等,即就是给自身赋值,直接返回*this;
	{
		delete[]m_pData;  //释放原实例中 m_pData的内存
		m_pData = NULL;

		m_pData = new char[strlen(str.m_pData) + 1];
		strcpy(m_pData, str.m_pData);  //重新申请空间并完成拷贝
	}
    return *this;
}
但是,以上代码书上说,还存在安全问题,说是,上例的赋值运算重载中释放了原有的实例对象内存,而去重新申请了内存,但是,一旦申请内存失败,也就是说new char 抛出了异常,m_pData将是一个空指针,问题就是一大堆,怎么办呢?一种方法是:先new 一块新内存,在delete释放已有的内存,这样,只有在内存分配成功之后才会释放原有内容,分配失败,原来的实例也不会被修改;

MyString& MyString::operator=(const MyString& str)
{
	if (this != &str)
	{
		char* tmp = new char[strlen(str.m_pData) + 1];
		if (tmp != nullptr)
		{
			delete[]m_pData;
			m_pData = NULL;

			m_pData = tmp;
			strcpy(m_pData, str.m_pData);
		}
	}
    return *this;
}
还有更好的写法:

MyString& MyString::operator=(const MyString& str)
{
	if (this != &str)
	{
		MyString tmp(str);
		swap(m_pData,tmp.m_pData);  //库中交换函数 swap();
	}
	return *this;
}

还有大神是这样写的;

String& operator=(String rhs) // 传值
  {
    swap(rhs);
    return *this;
  }
 

拙见,欢迎纠正;
good