如何实现一个赋值运算符重载函数呢?
我们要考虑以下几个问题
1、首先要考虑的是该函数的返回值,应该是该类型的引用,并在函数结束前返回一个自身的引用(*this)
这样做的目的是:实现连续赋值操作
2、其次要考虑的是参数,由于传值会进行拷贝构造,会造成一定的资源浪费,所以在传参时应该传引用;在传参的过程中,实例的状态不会发生改变,所以使用const关键字
3、在赋值的过程中还存在开辟新空间以及释放资源问题,在开辟新空间前要释放自身已有的内存,并且置空
这样做的目的是:防止内存泄漏
4、在释放内存前还要考虑传入的参数是否与当前实例相同,若相同则直接返回,不进行释放内存这步操作,若相同再释放内存就会将当前实例的内存和传入参数的内存全部释放,就无法完成赋值操作
具体的代码示例如下:
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];
strcpy(m_pData,str,m_pData);
return *this;
}
这样的代码其实还存在安全性问题,如果此时内存不足会导致new char抛出异常,m_pData是一个空指针,就会导致程序崩溃。
要想解决赋值运算符函数实现中出现的异常安全性,有两种方法:
第一方法是先用new分配新内容,再用delete释放已有的内容
第二种方法是先创建一个临时实例,再交换临时实例和原来的实例
用第二种实现的代码如下:
CMystring &CMystring::operator(const CMystring &str)
{
if(this != &str)
{
CMystring strTemp(str);
char* pTemp = strTemp.m_pData;
strTemp.m_pData=m_pData;
m_pData=pTemp;
}
return *this;
}
先创建一个临时实例strTemp,然后把strTemp.m_pData和实例自身的m_pData进行交换。
在CMyString的构造函数里用new分配内存,如果内存不足会抛出异常,此时还没有修改原来实例的状态,因此实例的状态还是有效的,也就保证了异常安全性。