题目:如下类型为CMyString的声明,请为该类型添加赋值运算符函数。
 
class CMyString
{
public:
     CMyString(char* pData = NULL);
     CMyString(const CMyString& str);
     ~CMyString();
 
private:
     char* m_pData;
};

 

关注点:
 
     1.是否把返回值的类型声明为该类型的引用,并在函数结束前返回实例自身的引用(即*this)。只有返回一个引用,才可以允许连续赋值(str1=str2=str3);
     2.是否把传入的参数的类型声明为常量引用。如果传入的的参数不是引用而是实例,那么从形参到实参会调用一次复制构造函数。把参数声明为引用可以避免这种无谓的消耗,提高代码效率。同时,我们在赋值运算符函数内不会改变传入实例的状态,因此该为传入的引用参数加上const关键字;
     3.是否释放实例自身已有的内存。如果我们忘记在分配新内存之前释放自身已有的空间,程序将出现内存泄漏;
     4.是否判断传入的参数和当前实例(*this)是不是同一个实例。如果是同一个,则不进行赋值操作,直接返回。如果事先不判断就进行赋值那么在释放实例自身的内存的时候就会导致严重的问题。当*this和传入的参数是同一个实例时,那么一旦释放了自身的内存,传入的参数的内存也同时被释放了,因此再也找不到需要赋值的内容了。
 
解法一:经典的解法
     
  当完整的考虑上述四个方面后,写下如下代码。
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将是一个空指针,这样非常容易造成程序崩溃。要想在赋值运算符函数中实现异常安全性,有两种方法。一个简单的办法是我们先用new分配新内容再用delete释放已有的内容。这样只在分配内容成功之后再释放原因的内容,也就是当分配内存失败时我们能确保CMyString的实例不会被修改。还有一个更好的办法是先创建一个临时实例,再交换实例和原来的实例。
 
CMyString& CMyString::operator =(const CMyString& str)
{
     if (this != &str)
     {
           CMyString strTemmp(str);
 
           char* pTemp = strTemmp.m_pData;
           strTemmp.m_pData = m_pData;
           m_pData = pTemp;
     }
 
     return *this;
}

 

 
 
 
posted @ 2017-04-03 22:31 风xmx 阅读(248) 评论(0) 推荐(0) 编辑
摘要: 计数排序是一种稳定的排序算法,它不是比较排序。计数排序是有条件限制的:排序的数必须是n个0到k的数,所以计数排序不适合给字母排序。计数排序时间复杂度:O(n+k),空间复杂度:O(k),当k=n时,时间复杂度可以达到O(n)。计数排序思想:给定一个符合规定的无序数组,先求出这个数组中最大的数,... 阅读全文
posted @ 2014-07-03 20:40 风xmx 阅读(573) 评论(0) 推荐(0) 编辑
摘要: 快速排序是对冒泡排序算法的一种改进型算法,而且快速排序也采用了分治法的思想。快速排序是不稳定排序,平均时间复杂度为:O(n*logn),最坏时间复杂度为:O(n*n),空间时间复杂度:O(logn),但快速排序通常是用于排序的最佳实用的选择。 快速排序的思想:从这段数组选取一个数(通常是第... 阅读全文
posted @ 2014-07-03 20:36 风xmx 阅读(324) 评论(0) 推荐(0) 编辑
摘要: 堆数据结构是一种数组对象,它可以被视为一棵完全二叉树。时间复杂度为:O(n*logn),空间复杂度:O(1);平均时间复杂度和最坏时间复杂度都为:O(n*logn),但堆排序是不稳定排序。堆排序思路: 1.建立小堆:把堆看成一个完全二叉树,然后从这棵树的最后一个非叶子节点开始,... 阅读全文
posted @ 2014-07-03 20:34 风xmx 阅读(343) 评论(0) 推荐(0) 编辑
摘要: 一,归并排序 归并排序是建立在归并操作上的一种排序算法,它采用了分治法的思想,是一种稳定的排序算法,而且归并排序的速度仅次于快速排序。时间复杂度:O(n*logn),最坏的情况:O(n*logn),空间复杂度:O(n)。从数据就可以看出:归并排序比快速排序快很多,同样为稳定排序。 ... 阅读全文
posted @ 2014-07-03 20:33 风xmx 阅读(405) 评论(0) 推荐(0) 编辑
摘要: 作为排序算法的一种,插入排序是稳定排序。它的时间复杂度:O(n*n),空间复杂度为:O(1)。最好的时间复杂度为:O(n),最坏和平均则为:O(n*n)。 算法的思想:给定一组无序的数组,我们从它的第二个数开始,并将它赋值给mark变量(mark变量就是要插入到其他位置去的数),让mark和... 阅读全文
posted @ 2014-07-03 20:30 风xmx 阅读(300) 评论(0) 推荐(0) 编辑
摘要: 建立一个有向图的邻接表,首先要构思好它的邻接表里面包含哪些结构数据,然后根据哪些数据来建立相应的结构体。但也要注意数据的输入。#include #include #define MAX_SIZE 10typedef struct ArcNode //弧节点结构体{ ... 阅读全文
posted @ 2014-07-03 20:27 风xmx 阅读(2304) 评论(0) 推荐(0) 编辑
摘要: 关于二叉树的遍历,递归遍历的话,就只要不断的递归就够啦,而非递归的话就需要用到栈和队列了,然而栈和队列也是我自己写的吧,就算是锻炼了一下自己对数据结构课的掌握吧,而非递归后序遍历二叉树参考了http://www.cnblogs.com/dolphin0520/archive/2011/08/25... 阅读全文
posted @ 2014-06-02 17:53 风xmx 阅读(24512) 评论(0) 推荐(3) 编辑
摘要: 从http://www.cnblogs.com/fzhe/archive/2013/01/07/2849040.html处转载。一、已知前序、中序遍历,求后序遍历例:前序遍历: GDAFEMHZ中序遍历: ADEFGHMZ画树求法:第一步,根据前序遍历的特点,我们知道根结点为G ... 阅读全文
posted @ 2014-05-13 19:17 风xmx 阅读(2656) 评论(0) 推荐(0) 编辑
摘要: 这个代码其实自己花了很长的时间去理解,渐渐的有所明白了一点。#include #include typedef enum { Link , Thread } PointTag; //Link表示指针,Thread表示线索typedef struct treenode ... 阅读全文
posted @ 2014-05-05 22:42 风xmx 阅读(279) 评论(0) 推荐(0) 编辑
点击右上角即可分享
微信分享提示