热门IT资讯网

c++中 有关自定义string的那些为什么

发表于:2024-11-25 作者:热门IT资讯网编辑
编辑最后更新 2024年11月25日,1、为什么我们要学会写自定义string类面试官爱考,你有办法吗,没有-.-2、自定义string类应该如何正确书写quote一句c++primer中的话:类的安全性和处理正确性的不够,需要类的设计者

1、为什么我们要学会写自定义string类

面试官爱考,你有办法吗,没有-.-

2、自定义string类应该如何正确书写

quote一句c++primer中的话:

类的安全性和处理正确性的不够,需要类的设计者(也就是我们)去写拷贝构造和赋值运算符重载函数,而最困难的不是如何书写而是让我们自己本身意识到需要这样做。


关于MyString不得不说的就是:深浅拷贝问题,这个究其原因就是它的成员变量是个char *类型的,如果我们懒到要让编译器自己帮我们去建构造、拷贝构造,赋值运算符重载这些函数,那么问题就是很大滴,因为它也很lazy,它做的操作就是让两个指针指向同一个地方。

举个栗子看:


那么下面就说说如何写一个正确的string:

首先c++中string它是个类对吧

那么我们就写一个类出来(成员函数和成员变量)

class MyString{private:        char *_pData;//对,你没看错,只需要一个char型指针就可以实现哦public:        //首先一个类要有构造函数-->保证类的成员变量被正确的初始化        //第一种写法----正确但不是最优        MyString(char *pData=NULL)        {                if (pData==NULL)                {                        _pData=new char[1];                        _pData[0]='\0';                }                else                {                        _pData=new char[strlen(pData)+1];                        strcpy(_pData,pData);                }        }        //第二种写法--比第一种更优:使用初始化列表        MyString(char *pData=NULL)                :pData(new char[strlen(pData)+1])        {                strcpy(_pData,pData);        }        //既然在构造中进行了new那么相对的是不是要在析构中去delete?        ~MyString()        {                if (_pData)//这里可以直接不用判断,think about why?                {                        delete []_pData;                }        }        //拷贝构造-----?为什么需要写,因为成员变量是指针,如果我们不进行自己去写        //就会出现安全性和正确性的问题,两个指针指向一个空间,当其中一个析构后,        //另外一个就无法再去访问这片空间,会出现非法操作        //考点:形参必须传入的是该类型的引用,不然在实参传给形参时        //就会发生值传递,进行拷贝构造,那么这个拷贝构造就是一个死循环        //第一种写法        MyString(const MyString &mstr)        {                if (strlen(mstr._pData)==0)                {                        _pData=new char[1];                        _pData[0]='\0';                }                else                {                        _pData=new char[strlen(mstr._pData)+1];                        strcpy(_pData,mstr._pData);                }        }        //第二种写法        MyString(const MyString &mstr)                :_pData(new char[strlen(mstr._pData)+1])        {                strcpy(_pData,mstr._pData);        }        //第三种写法:只有在构造和析构的时候开辟和释放空间,内存空间不易出错        //不会出现MyString实例化对象的错误,考虑到了异常安全性        MyString(const MyString &mstr)                :_pData(NULL)                //_pData没有初始化,随机的空间,如果不赋值为空,会delete失败        {                MyString temp(mstr._pData);                swap(temp._pData,_pData);        }        //赋值运算符重载        //考点:1、返回值是该类型引用(考虑到有连等情况a=b=c)        //考点:2、形参是const 引用(不会改变形参并且效率高)        //第一种写法--->缺点:如果在new char[]出错的话,很有可能_pData就变成野指针        //那么MyString返回的对象就是一个不正确的对象,有异常安全性问题        MyString& operator=(const MyString &mstr)        {                //考点:3、自己给自己赋值的情况,有没有考虑到!                if (this!=&mstr)                {                        //考点:4、先释放,一定是释放[]_pData,原因就是构造的方式                        delete []_pData;                        //再开辟                        _pData=new char[strlen(mstr._pData)+1];                        strcpy(_pData,mstr._pData);                }                return *this;        }        //第二种写法        MyString &operator=(const MyString &mstr)        {                //先开辟                char *temp=new char[strlen(mstr._pData)+1];                if (temp==NULL)                {                        return *this;                }                //在释放                delete []_pData;                _pData=temp;                strcpy(_pData,mstr._pData);                return *this;        }        //第三种写法        MyString &operator=(MyString mstr)        {                swap(mstr._pData,_pData);                return *this;        }        //更优写法        MyString &operator=(const MyString &mstr)        {            if(&mstr!=this)            {                MyString temp(mstr._pData);                swap(temp._pData,_pData);            }            return *this;        }        //String对象转换成const char*        const char* C_str()const        {                return _pData;        }        //求字符串长度        size_t Size()        {                return strlen(_pData);        }        //判断是否相等        bool operator==(const MyString &mstr)const        {                if (&mstr!=this)                {                        if(!strcmp(_pData,mstr._pData))                        {                                return false;                        }                }                return true;        }        //某个字符        char operator[](size_t pos)const        {                if (pos=0)                {                        return _pData[pos];                }                else                {                        return 0;                }        }        //字符串比较        int operator<(const MyString &mstr)const        {                int truth=strcmp(_pData,mstr._pData);                if (truth>0)                {                        return -1;                }                else if (truth==0)                {                        return 0;                }                else                {                        return 1;                }        }        };
0