码迷,mamicode.com
首页 > 其他好文 > 详细

3.异常安全的赋值运算符重载

时间:2015-03-21 15:27:19      阅读:132      评论:0      收藏:0      [点我收藏+]

标签:

一、题目

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

 1 class CMyString
 2 {
 3 public:
 4     CMyString(char* pData)
 5     {
 6         m_pData = new char[strlen(pData) + 1];
 7         strcpy(m_pData, pData);
 8     }
 9 
10     CMyString(): m_pData(NULL) {}
11 
12 
13     CMyString(const CMyString& str);
14     
15     ~CMyString()
16     {
17         delete []m_pData;
18     }
19 
20     CMyString& operator =(const CMyString& str);
21 
22     void Print() const
23     {
24         printf("%s\n", m_pData);
25     }
26 
27 
28 private:
29     char* m_pData;
30 };

二、经典解法

  经典解法代码实现如下:

 1 CMyString& CMyString::operator =(const CMyString &str)
 2 {
 3     // 自身赋值
 4     if (this == &str)
 5         return *this;
 6 
 7 
 8     m_pData = new char[strlen(str.m_pData) + 1]; // 加一,为存放字符串的结束符‘\0‘
 9     strcpy(m_pData, str.m_pData);
10 
11     return *this;
12 }

  这是一个经典的解法,为了防止自身赋值,先判断复制对象,是否是自身,如果是,则什么都不做。这个方法可以应对常规的情况。但是,其没有考虑异常安全。在这里的

new char[],可能会由于内存不足导致其抛出异常。

三、考虑异常安全的解法

  实现代码如下:

 1 CMyString& CMyString::operator =(const CMyString &str)
 2 {
 3     if (this != &str)
 4     {
 5         CMyString strTemp(str);
 6 
 7         char* pTemp = strTemp.m_pData;
 8         strTemp.m_pData = m_pData;
 9         m_pData = pTemp;
10     }
11 
12     return *this;
13 }

  在该赋值函数中,如果判断不是自身赋值,那么先用拷贝构造函数以str构造一个临时对象strTemp,此时对于char的内存分配转移到临时对象的拷贝构造函数中,如果抛出异常,那么对于该实例本身来说,没有任何改变,不影响该实例本身的使用。如果临时对象没有出异常,那么将实例自身的m_pData和strTemp.m_pData交换,由于strTemp是临时对象,在作用域结束时,自动调用析构函数,释放内存,而此时的strTemp的m_pData已经指向了原实例的m_pData的内存。这样就能自动释放内存了。同时也是异常安全的。

  

3.异常安全的赋值运算符重载

标签:

原文地址:http://www.cnblogs.com/wangjzh/p/4355514.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!