声明一个字符串类,为这个类型添加赋值运算符
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