剑指Offer-题1-赋值运算符函数

Author Avatar
Orange 3月 24, 2018
  • 在其它设备中阅读本文章

题目:赋值运算符函数

如下为类型CMyString的声明,请为该类型添加赋值运算符函数。

1
2
3
4
5
6
7
8
9
class CMyString{
public:
CMyString(char* pData=NULL);
CMyString(const CMyString& str);
~CMyString(void);

private:
char *m_pData;
};

解析

题目考察赋值运算符(=)函数声明,对于

1
2
3
int a;
// 调用赋值运算符函数
a = 1;

考虑形如 a = 1 ,视 aint 对象则代码改为 a.=(1),其中 = 为方法名, 1 为实参,由此构造出函数声明雏形

1
返回值 =(int num);

因为 printf("%d", a = 1) 输出值为运算结果,故而

1
int =(int num);

由于运算符函数特殊性,函数名加上关键词operator

1
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
9
class 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
6
CMyString& 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
10
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;
}

然而,事情并没有这么简单……,书中神级代码

1
2
3
4
5
6
7
8
9
10
11
CMyString& 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许可协议署名非商业性使用相同方式共享
本文采用 CC BY-NC-SA 3.0 Unported 协议进行许可