赋值运算符函数

来源:互联网 发布:淘宝查看在线人数插件 编辑:程序博客网 时间:2024/05/12 11:24

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

#include <iostream>using namespace std;class CMyString{public:CMyString(char* pData=NULL);CMyString(const CMyString& str);~CMyString(void)private:char *m_pData;};

注意的点:

(1)是否把返回值的类型声明为该类型的引用,并在函数结束前返回实例自身的引用(*this)。只有返回一个引用,才可以允许连续赋值。否则如果函数的返回值为void,应用该赋值运算符将不能做连续赋值

(2)是否把传入的参数的类型声明为常量引用。如果传入的参数不是引用而是实例,那么从形参到实参会调用一次复制构造函数。把参数的声明为引用可以避免这样无谓的消耗,能提高代码的效率。同时,我们在赋值运算符函数中不会改变传入的实例的状态,因此应该为传入的引用参数加上const关键字。

(3)是否释放实例自身已有的内存。如果我们忘记在分配新内存之前释放自身已有的内存,程序将出现内存泄露。

(4)是否判断传入的参数和当前的实例(*this)是不是同一个实例。


经典解法:

#include <iostream>using namespace std;class CMyString{public:CMyString(char* pData=NULL);CMyString(const CMyString& str);CMyString& operator = (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;}

分析:前面的函数在分配内存之前先用delete释放了实例m_pData的内存。如果此时内存不足导致new char抛出异常,m_pData将是一个空指针,这样非常容易导致程序崩溃。也就是说一旦在赋值运算符函数内部抛出一个异常,CMyString的实例不再持有效的状态,这就违背了异常安全的原则。


考虑异常安全性的解法:

#include <iostream>using namespace std;class CMyString{public:CMyString(char* pData=NULL);CMyString(const CMyString& str);CMyString& operator = (const CMyString& str);~CMyString(void)private:char *m_pData;};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;}




1 0
原创粉丝点击