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<strlen(_pData)&&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;
}
}
};
亿速云「云服务器」,即开即用、新一代英特尔至强铂金CPU、三副本存储NVMe SSD云盘,价格低至29元/月。点击查看>>
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。