题目:如下为类型CMyString 的声明,请为该类型添加赋值运算符
class CMyString{
public:
CMyString(char* pData = nullptr);
CMyString(const CMyString& str);
~CMyString(void);
private:
char* m_pData;
};
普通写法:
CMyString &CMyString::operator=(const CMyString &str) // 如果传入的参数不是引用而是实例,那么从形参到实参会调用一次复制构造函数,造成浪费,在赋值运算函数内不会改变传入的实例的状态,所以用const 关键字
{
if (this == &str) {
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 将是一个空指针,这样非常容易导致程序崩溃,违背 异常安全性原则
安全写法:
CMyString &CMyString::operator=(const CMyString &str)
{
/*
if (this == &str) {
return *this;
}
delete[] m_pData;
m_pData = nullptr;
m_pData = new char[strlen(str.m_pData) + 1];
strcpy(m_pData, str.m_pData);
*/
if (this != &str) {
CMyString strTemp(str);
char *pTemp = strTemp.m_pData;
strTemp.m_pData = m_pData;
m_pData = pTemp;
}
return *this;
}
在这个函数中,我们先创建一个临时实例 str Temp,接着把 strTemp.m_pData 和实例自身的 mpData 进行交换。由于strTemp 是一个局部变量,但程序运行到 记 的外面时也就出了该变量的作用域,就会自动调用 strTemp的析构函数,把strTemp.m pData所指向的内存释放掉。由于
str Temp.m pData 指向的内存就是实例之前 m pData 的内存,这就相当于自动调用析构函数释放实例的内存。
完整代码:
#include <QCoreApplication>
#include <cstring>
#include <iostream>
#include <ostream>
class CMyString
{
public:
CMyString(char *pData = nullptr);
CMyString(const CMyString &str);
~CMyString(void);
CMyString &operator=(const CMyString &str);
friend std::ostream &operator<<(std::ostream &os, const CMyString &str);
private:
char *m_pData;
};
CMyString &CMyString::operator=(const CMyString &str)
{
/*
if (this == &str) {
return *this;
}
delete[] m_pData;
m_pData = nullptr;
m_pData = new char[strlen(str.m_pData) + 1];
strcpy(m_pData, str.m_pData);
*/
if (this != &str) {
CMyString strTemp(str);
char *pTemp = strTemp.m_pData;
strTemp.m_pData = m_pData;
m_pData = pTemp;
}
return *this;
}
CMyString::CMyString(char *pData)
{
if (pData == nullptr) {
m_pData = new char(1);
m_pData[0] = '\0';
} else {
int len = strlen(pData) + 1;
m_pData = new char(len);
m_pData = pData;
}
}
CMyString::~CMyString(void)
{
delete m_pData;
m_pData = nullptr;
}
CMyString::CMyString(const CMyString &str)
{
int len = strlen(str.m_pData) + 1;
m_pData = new char(len);
m_pData = str.m_pData;
}
std::ostream &operator<<(std::ostream &os, const CMyString &str)
{
os << str.m_pData;
return os;
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
char *c = "string";
CMyString b(c);
CMyString d = b;
std::cout << "b = " << b << " "
<< "d =" << d << std::endl;
return a.exec();
}