zoukankan      html  css  js  c++  java
  • 【C++】CMyString的实现

    面向对象的编程,首先得设计出良好的类体结构和接口,然后是合理的实现.

    如何自己设计并实现一个字符串类?这个问题看似简单,其实里面也有不少的玄机.

     1 class CMyString
     2 {
     3 public:
     4     CMyString(char* pStr = NULL);
     5     CMyString(const CMyString& rhs);
     6     CMyString& operator=(const CMyString& rhs);
     7     ~CMyString();
     8     .....    
     9 private:
    10     char* pData;
    11     int len;        //当前字符串长度,不包括'\0'
    12 };

    CMyString类中包含指向动态分配内存的指针,因而需要自定义copying函数

    CMyString类中字符串长度表示当前字符串长度,不包括'\0',在构造字符串时,保证字符串以'\0'结尾

     1 CMyString::CMyString(char *pStr = NULL)
     2 {
     3     if(pStr == NULL)
     4     {
     5         pData = NULL;
     6         len = 0;
     7     }
     8     else
     9     {
    10         len = strlen(pStr);
    11         pData = (char*)malloc(sizeof(char) * (len + 1));
    12         memset(pData,'/0',sizeof(char) * (len + 1));
    13         strcpy(pData,pStr);
    14     }
    15 }
    16 
    17 CMyString::~CMyString()
    18 {
    19     if(pData != NULL)
    20     {
    21         free(pData);
    22         pData = NULL;
    23         len = 0;
    24     }
    25 }

    以C语言函数为基础完成构造函数与析构函数.

    copying函数的实现如下:

     1 CMyString::CMyString(const CMyString &rhs)
     2 {
     3     memcpy(this,&rhs,sizeof(CMyString);
     4 }
     5 
     6 CMyString& CMyString::operator=(const CMyString &rhs)
     7 {
     8     CMyString *pStr;
     9     pStr = new CMyString(rhs);        //调用copy constructor
    10     return *pStr;
    11 }

    上述代码实现存在以下几个问题:

    1.copy constructor实现过程,参用的是浅拷贝方式新建的CMyString对象中的pData指针和rhs对象中的pData指针指向同一块内存区域.

    2.operator=实现过程,是调用copy constructor创建一个新对象,并返回,将会丢失当前this指针所对应的对象,与operator=的含义不符.

    operator=是对已经存在的对象进行赋值,而不是重新创建一个对象.

    正如<<Effective C++>>提到的,不应该以某个copying函数去实现另一个copying函数.应该将共同机能放进第三个函数中,并由两个copying函数共调用.

    针对上述不合理的代码,进行修正,得到如下的代码:

     1 CMyString::CMyString(const CMyString& rhs)
     2 {
     3     if(rhs.pData == NULL)
     4     {
     5         pData = NULL;
     6         len = 0;
     7     }
     8     else
     9     {            
    10         pData = (char*)malloc(sizeof(char) * (rhs.len + 1));
    11         memset(pData,'/0',sizeof(char) * (rhs.len + 1));
    12         len = rhs.len;            //通过对象访问私有成员变量
    13         strcpy(pData,rhs.pData);
    14     }
    15 }
    16 CMyString& CMyString::operator=(const CMyString& rhs)
    17 {
    18     if(this = &rhs)        //证同测试
    19         return *this;
    20     if(pData != NULL)    //*this不是空字符串
    21     {
    22         free(pData);    //释放实例自身已有内存
    23     }
    24     pData = (char*)malloc(sizeof(char) * (rhs.len + 1));
    25     memset(pData,'/0',sizeof(char) * (rhs.len + 1));
    26     len = rhs.len;            //通过对象访问私有成员变量
    27     strcpy(pData,rhs.pData);
    28 }

    经过修正后,解决了浅拷贝和当前this所指向对象丢失的问题,但这个实现仍不是异常安全的.

    在operator=中,如果第24行分配内存失败,产生异常.此时当前的pData所指向内存已被释放,导致pData指向空指针

    此外,第12行代码中,为什么可以通过对象访问私有成员变量,其详细解释请参考:

    http://www.cnblogs.com/dwdxdy/archive/2012/07/17/2595741.html

    上述解决方法时,可以利用临时指针保存当前的pData,然后当完成赋值操作后,再根据临时指针释放原始pData所指的空间

     1 CMyString& CMyString::operator=(const CMyString& rhs)
     2 {
     3     char* pOri = pData;                //保存原始指针
     4     pData = (char*)malloc(sizeof(char) * (rhs.len + 1));
     5     memset(pData,'/0',sizeof(char) * (rhs.len + 1));
     6     len = rhs.len;
     7     strcpy(pData,rhs.pData);
     8     free(pOri);                        //释放原始指针所指内存
     9     return *this;
    10 }

    这种实现,当前rhs和*this是同一个对象,也可以安全完成赋值操作.

    参考资料:

    Effective C++

    http://www.cnblogs.com/xwdreamer/archive/2012/05/14/2500632.html

    http://blog.csdn.net/zijinshi/article/details/111039

    http://www.cnblogs.com/dwdxdy/archive/2012/07/17/2595821.html

  • 相关阅读:
    记一次在线阅卷系统设计开发总结
    卡座录音经验汇总
    TEAC 6030S 统调
    空白磁带SONY TDK 万胜,3大品牌空白磁带,入门必读
    cnetos 7 mysql 从data还原数据库
    java的BigDecimal比较大小
    nginx配置静态访问txt文件
    小程序筛选
    买分产整合
    开窗函数
  • 原文地址:https://www.cnblogs.com/dwdxdy/p/2602303.html
Copyright © 2011-2022 走看看