自我实现一个简洁版的String类——1-创新互联

在C++中有C没有的string字符串类型,string类型的数据其实是一个指向字符串首地址的指针变量,因此在string类的默认成员函数拷贝构造和赋值运算符的重载就会涉及到深浅拷贝的问题,一不小心要么就是内存泄露要么就是多次释放同一块空间导致程序崩溃,下面就来模拟实现一个简洁版的String类:

东台ssl适用于网站、小程序/APP、API接口等需要进行数据传输应用场景,ssl证书未来市场广阔!成为创新互联建站的ssl证书销售渠道,可以享受市场价格4-6折优惠!如果有意向欢迎电话联系或者加微信:13518219792(备注:SSL证书合作)期待与您的合作!

  既然是指向一个字符串的指针,因此类的成员变量就需要有一个char*类型的指针;

#include 
#include 
using namespace std;

class CMyString
{
public:
    CMyString(const char* str);
    CMyString(const CMyString& s); 
    CMyString& operator=(CMyString s); 
    //CMyString& operator=(const CMyString& s);
    ~CMyString();

    void print_string();

private:
    char* _str;
};

上面为简单的CMyString类的声明,接下来要实现最主要的四个默认的成员函数:

构造函数主要是为成员变量_str分配内存空间并且初始化为形参的值;

CMyString::CMyString(const char* str)   //含参的构造函数
    :_str(NULL)
{
        assert(str);
    _str = new char[_capacity];
    strcpy(_str, str);
}
CMyString::CMyString()    //默认的构造函数
        :_str(NULL)
    {}

拷贝构造就会涉及到了深浅拷贝的问题,因为不能使两个字符串的指针指向同一块地址空间:

CMyString::CMyString(const CMyString& s)
        :_str(NULL)
{
        CMyString tmp(s._str);//用前面实现的构造函数构造出一个值为s._str的临时类对象
    swap(_str, tmp._str);//交换临时类的字符串和_str,这样当tmp出了作用域就会自动释放
}

赋值运算符的重载函数同样会涉及到深浅拷贝的问题:

//这是一种比较现代的写法,没有用引用s就为一个临时的类对象,出了作用域就会自动调用析构函数
CMyString& CMyString::operator=(CMyString s)
{
    if(strcmp(s._str, _str) != 0)
        swap(_str, s._str);//交换二者的值就能将有效值赋给_str,而原来的值随s释放
    return *this;
}

//较为传统的写法,先要判断是否自己给自己赋值再释放自己空间,重新开辟一块空间拷贝所需值
//CMyString& CMyString::operator=(const CMyString& s)
//{
//  if(this != &s)
//  {
//      delete[] _str;
//      _str = new char[strlen(s.str)+1];
//      strcpy(_str, s._str);
//  }
//  return *this;
//}

但是在上面注释掉的一种写法中存在一个问题,就是如果将自己本身的地址空间释放掉了之后,再去new一块空间有可能会new不出来,这样的话不仅不能成功赋值,连自身本就存在的值也丢掉了,因此可以优化为如下代码:

CMyString& CMyString::operator=(const CMyString& s)
{
    if(this != &s)
    {
        char *tmp = new char[strlen(s.str)+1];
        if(tmp != NULL)
        {
            delete[] _str;
            _str = tmp;
            strcpy(_str, s.str);
        }
    }
    return *this;
}

析构函数是在当类对象出了所在作用域时自动调用完成清理工作的:

CMyString::~CMyString()
{
    if(_str != NULL)       //检查类成员是否为空,delete不能释放空指针
    {   
        delete[] _str;
        _str = NULL;       //防止出现野指针
    }   
}

最后一个print_string函数是为了打印验证结果,这里就不写了;

main函数:

int main()
{
    CMyString s1("this is my string...");
    s1.print_string();
    CMyString s2("hello world...");
    s2.print_string();
    CMyString s3(s2);
    s3.print_string();
    s3 = s1;
    s3.print_string();

    return 0;
}

运行程序结果如下:

自我实现一个简洁版的String类——1

《完》

另外有需要云服务器可以了解下创新互联scvps.cn,海内外云服务器15元起步,三天无理由+7*72小时售后在线,公司持有idc许可证,提供“云服务器、裸金属服务器、高防服务器、香港服务器、美国服务器、虚拟主机、免备案服务器”等云主机租用服务以及企业上云的综合解决方案,具有“安全稳定、简单易用、服务可用性高、性价比高”等特点与优势,专为企业上云打造定制,能够满足用户丰富、多元化的应用场景需求。


本文标题:自我实现一个简洁版的String类——1-创新互联
本文网址:http://hbruida.cn/article/cchdsc.html