剑指Offer-题1-赋值运算符函数
题目:赋值运算符函数
如下为类型CMyString的声明,请为该类型添加赋值运算符函数。1
2
3
4
5
6
7
8
9class CMyString{
public:
CMyString(char* pData=NULL);
CMyString(const CMyString& str);
~CMyString(void);
private:
char *m_pData;
};
解析
题目考察赋值运算符(=)函数声明,对于1
2
3int a;
// 调用赋值运算符函数
a = 1;
考虑形如 a = 1
,视 a
为 int
对象则代码改为 a.=(1)
,其中 =
为方法名, 1
为实参,由此构造出函数声明雏形1
返回值 =(int num);
因为 printf("%d", a = 1)
输出值为运算结果,故而1
int =(int num);
由于运算符函数特殊性,函数名加上关键词operator1
int operator=(int num);
考虑函数仅对实参取值,故参数可常类型(const)引用传递,修改声明1
int operator= (const int& num);
考虑以下任意一种情况
(a = 1) = 2
运行通过说明(a = 1)
返回值为可修改的左值即a
cout << ... << ...
中的运算符函数<<
可流式编写,说明cout << ...
返回值为可修改左值即std::out&
故返回值需引用传递,修改声明1
int& operator= (int& num);
套用进类 CMyString
1
2
3
4
5
6
7
8
9class CMyString{
public:
CMyString(char* pData=NULL);
CMyString(const CMyString& str);
~CMyString(void);
CMyString& operator=(const CMyString& str);
private:
char *m_pData;
};
顺便把定义写了(应该是”深拷贝”赋值)1
2
3
4
5
6CMyString& operator=(const CMyString& str)
{
m_pData = new char[strlen(str.m_pData) + 1];
strcpy(m_pData, str.m_pData);
return *this;
}
对照书本发现自己还是太嫩了,没有对各个变量进行判断,安全代码1
2
3
4
5
6
7
8
9
10CMyString& 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;
}
然而,事情并没有这么简单……,书中神级代码1
2
3
4
5
6
7
8
9
10
11CMyString& operator=(const CMyString& str)
{
if (&str != this)
{
// (代码异常安全性)将new操作置于构造函数中,可保护当前m_pData数据免受delete
CMyString strTemp(str);
char *pTemp = strTemp.m_pData;
strTemp.m_pData = this->m_pData;
this->m_pData = pTemp;
}
}
本文采用 CC BY-NC-SA 3.0 Unported 协议进行许可