剑指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)返回值为可修改的左值即acout << ... << ...中的运算符函数<<可流式编写,说明cout << ...返回值为可修改左值即std::out&
故返回值需引用传递,修改声明1
int& operator= (int& num);
套用进类 CMyString1
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 协议进行许可



