剑指Offer面试题1:赋值运算符函数

题目:

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

class CMyString {
    public:
        CMyString(char* pData = NULL);
        CMyString(const CMyString& str);
        ~CMyString(void);
    private:
        char* m_pData;
};

实现:

CMyString& CMyString operator = (const CMyString &str){
    if(this == &str)
        return *this;

    delete []m_pData;
    m_pData = NULL;
    m_pData = new char[strlen(str.m_pData) + 1];
    strcpy(m_pData, str.m_pData);

    return *this;
}

四个注意的点:

返回值类型:返回值类型是声明类型的引用,并在函数结束前返回实例自身的引用(*this)。原因:只有返回引用才能进行连续的赋值操作,如str1 = str2 = str3。
传入参数类型:传入参数的类型是常量的引用。原因:传入的是实例时,在形参到实参转化的时候会调用一次复制构造函数,这就造成无所谓的消耗。其次由于赋值运算不改变实例的状态,传入的引用参数上加const关键字。
释放自身的内存:在分配内存之前释放自身已有的内存,防止出现内存的泄漏。
传入参数和当前实例是否是同一个实例的判断:如果是同一个实例直接返回,不进行赋值操作,如果不判断直接赋值,在是同一个实例的情况下,释放实例自身内存的时候,传入参数的实参内存也被释放了,找不到要赋值的内容,出现很大的问题。

改进:

CMyString& CMyString operator =(const CMyString &str){
    if(this != &str){
        CMyString strTemp(str);     
        char *pTemp = strTemp.m_pData;
        strTemp.m_pData = m_pData;
        m_pData = pTemp;
    }
    return *this;
}

在分配内存之前先delete释放了m_pData的内存,在申请分配内存,如果此时的内存不足时会导致new char抛出异常,m_pData变成一个空指针,容易导致程序崩溃。
改进的优点在于:在delete之前先创建了一个临时的实例,这样交换指针所指的位置,而指向原来实例的局部变量会在if之外(作用域之外)自动调用strTemp的析构函数,把之前的实例所占用的内存释放掉。

猜你喜欢

转载自blog.csdn.net/u013108511/article/details/80295631