博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
C++ —模拟实现 string类
阅读量:4183 次
发布时间:2019-05-26

本文共 5364 字,大约阅读时间需要 17 分钟。

String类:标准库类型string类表示可变长的字符序列,定义在std中,专门用来管理字符串,下面一起看下它的重要考点。

一:浅拷贝:

class String{public:    String(const char* pStr = "")//构造函数        :_pStr(new char[strlen(pStr)+1])    {        if(0 == *pStr)//字符串为空        {            *_pStr = '\0';        }        else//字符串不为空        {            strcpy(_pStr,pStr);        }    }    String(const String& s)//拷贝构造函数    {        _pStr = s._pStr;    }    String& operator=(String& s)//赋值运算符重载    {        if(_pStr != s._pStr)//判断是不是自己给自己赋值        {            _pStr = s._pStr;        }        return *this;    }    ~String()//析构函数    {        if(NULL == _pStr)        {            return;        }        else        {            delete []_pStr;            _pStr = NULL;        }    }private:    char* _pStr;};

二:string四个版本的模拟实现:

1. 深拷贝普通版本

class string{public:    //构造函数    string(const char* ptr = "")    {        if (ptr == NULL)        {            _ptr = new char[1];            *_ptr = '\0';        }        _ptr = new char[strlen(ptr) + 1];        strcpy(_ptr, ptr);    }    //拷贝构造函数    string(const string& s)        :_ptr(new char[strlen(s._ptr)+1])    {        strcpy(_ptr, s._ptr);    }    string& operator=(const string& s)    {        if (this != &s)        {            char* tmp = new char[strlen(s._ptr) + 1];            strcpy(tmp, s._ptr);            delete[] _ptr;            _ptr = tmp;        }        return *this;    }    ~string()    {        if (_ptr)        {            delete[] _ptr;            _ptr = NULL;        }    }private:    char* _ptr;};

2. 深拷贝简洁版

版本1:

class string{public:    //构造函数    string(const char* ptr = "")    {        if (ptr == NULL)        {            _ptr = new char[1];            *_ptr = '\0';        }        _ptr = new char[strlen(ptr) + 1];        strcpy(_ptr, ptr);    }    //拷贝构造函数    string(const string& s)        :_ptr(new char[strlen(s._ptr)+1])    {        strcpy(_ptr, s._ptr);    }    string& operator=(const string& s)    {        if (_ptr!=s.ptr)        {            delete[] _ptr;            _ptr = new char[strlen(s._ptr) + 1];            strcpy(_ptr, s._ptr);        }        return *this;    }    ~string()    {        if (_ptr)        {            delete[] _ptr;            _ptr = NULL;        }    }private:    char* _ptr;};

版本2:

class string{public:    //构造函数    string(const char* ptr = "")    {        if (ptr == NULL)        {            _ptr = new char[1];            *_ptr = '\0';        }        _ptr = new char[strlen(ptr) + 1];        strcpy(_ptr, ptr);    }    //拷贝构造函数    string(const string& s)        :_ptr(NULL)    {        string tmp(s._ptr);        std::swap(_ptr, tmp._ptr);    }    string& operator=(const string& s)    {        if (_ptr!=s._ptr)        {            string tmp(s._ptr);            std::swap(_ptr,tmp._ptr);        }        return *this;    }    ~string()    {        if (_ptr)        {            delete[] _ptr;            _ptr = NULL;        }    }private:    char* _ptr;};

3. 引用计数

class string{public:    //构造函数    string(const char* ptr = "")        :_count(new int[0])        , _ptr(new char[strlen(ptr)+1])    {        if (ptr == NULL)        {            _ptr = new char[1];            *_ptr = '\0';        }        else            strcpy(_ptr, ptr);        *_count = 1;    }    //拷贝构造函数    string(const string& s)        :_count(s._count)    {        _ptr = (char*)(s._ptr);        _count = s._count;        (*_count)++;    }    string& operator=(const string& s)    {        if (_ptr!=s._ptr)        {            _ptr = s._ptr;            _count = s._count;            (*_count)++;        }        return *this;    }    ~string()    {        if (_ptr == NULL)            return;        else        {            if (--(*_count)==0)            {                delete[] _ptr;                delete[] _count;                _ptr = NULL;                _count = NULL;            }        }    }private:    char* _ptr;    int* _count;};

4. 写时拷贝

class string{public:    string(const char* ptr="")        :_ptr(new char[strlen(ptr)+4+1])//每次多创建4个空间来存放当前地址有几个对象    {        if (_ptr == NULL)        {            (*(int*)_ptr) = 1;//前四个字节拿来计数            _ptr += 4;            *_ptr = '\0';        }        else        {            (*(int*)_ptr) = 1;            _ptr += 4;            strcpy(_ptr, ptr);        }    }    string(const string& s)        :_ptr(s._ptr)    {        ++(*(int*)(_ptr - 4));//向前偏移4个字节将计数加1    }    string& operator=(const string& s)    {        if (_ptr != s._ptr)        {            if (--(*(int*)(_ptr-4)) == 0)            {                delete[] _ptr;                _ptr = NULL;            }            _ptr = s._ptr;            ++(*(int*)(_ptr - 4));        }    }    ~string()    {        if (_ptr == NULL)        {            return;        }        else        {            if (--(*(int*)(_ptr - 4)) == 0)            {                delete[] (_ptr-4);                _ptr = NULL;            }        }    }    char& operator[](size_t index)//下标访问操作符重载    {        assert(index >= 0 && index < strlen(_ptr));        if ((*(int*)(_ptr - 4))>1)//多个对象指向同一块空间        {            char* tmp = new char[strlen(_ptr) + 4 + 1];//新开辟一块空间            tmp += 4;//向后偏移4            strcpy(tmp,_ptr);            --(*(int*)(_ptr - 4));//将原来空间的计数器减1            _ptr = tmp;//将当前对象指向临时空间            *((int*)(_ptr - 4)) = 1;//将新空间的计数器变为1        }        return _ptr[index];    }private:    char* _ptr;};

转载地址:http://wxuoi.baihongyu.com/

你可能感兴趣的文章
struts2中的constant简介
查看>>
spring security 3.X 入门例子
查看>>
Win7 下安装Win8到U盘移动硬盘的方法
查看>>
sql server 2008 express 安装的时提示“重启计算机失败"
查看>>
在C#的窗体上添加个ActiveX控件
查看>>
nginx日志切割简介
查看>>
linux下lsof程序简介
查看>>
windows下taskkill命令简介
查看>>
RH5.4下升级python到2.7版本
查看>>
linux下修改ssh默认端口号
查看>>
SSH Secure Shell Client用密钥认证登录linux服务器
查看>>
Nginx 日志格式简介
查看>>
python中字符串前加r或R简介
查看>>
sqlmap简介
查看>>
Metasploit简介
查看>>
metasploit扫描mysql口令简介
查看>>
linux中/etc/passwd文件简介
查看>>
linux中的/etc/shadow文件简介
查看>>
EICAR标准反病毒测试文件简介
查看>>
SetTimer和KillTimer函数简介
查看>>