C++ string类
string类是C++的一个常见的面试题,考查面试者的基本功,虽然简单,但是有很多细节需要注意。
#pragmaonce#include<assert.h>/*深拷贝与浅拷贝:浅拷贝,只是对指针的拷贝,拷贝后两个指针指向同一个内存空间,深拷贝不但对指针进行拷贝,而且对指针指向的内容进行拷贝,经深拷贝后的指针是指向两个不同地址的指针。浅拷贝是指源对象与拷贝对象共用一份实体,仅仅是引用的变量不同(名称不同)。对其中任何一个对象的改动都会影响另外一个对象。深拷贝是指源对象与拷贝对象互相独立,其中任何一个对象的改动都不会对另外一个对象造成影响。举个例子,一个人名叫张三,后来用他克隆(假设法律允许)了另外一个人,叫李四,不管是张三缺胳膊少腿还是李四缺胳膊少腿都不会影响另外一个人。*/classString{friendostream&operator<<(ostream&_cout,constString&s);public:/*String():_pStr(/*newchar('\0')*/newchar[1]){_pStr[0]='\0';//不能是"\0"}//new和delete,new[]和delete[]一定要匹配使用//strlen不能传NULLString(char*pStr):_pStr(newchar[strlen(pStr)+1]){strcpy(_pStr,pStr);//strcpy会拷贝'\0'过去}*///构造函数合并String(char*pStr=""){_size=strlen(pStr);_capacity=_size+1;_pStr=newchar[_size+1];strcpy(_pStr,pStr);}/*//拷贝构造函数常规写法String(constString&s):_pStr(newchar[strlen(s._pStr)+1]){strcpy(_pStr,s._pStr);}*/String(constString&s):_pStr(NULL)//需要先将this->_pStr置为空,否则交换后tmp为随机值,析构tmp时delete[]出现错误{Stringtmp(s._pStr);std::swap(_pStr,tmp._pStr);}/*//赋值运算符重载常规写法->释放原来的空间,开辟和s一样大的空间String&operator=(constString&s){if(this!=&s){/*//存在一致性问题。如果new空间失败,原来的空间将被释放,深拷贝失败delete[]_pStr;_str=newchar[strlen(s._pStr)+1];strcpy(_pStr,s._pStr);*///先开辟空间,再拷贝char*tmp=newchar[strlen(s._pStr)+1];strcpy(tmp,s._pStr);delete[]_pStr;_pStr=tmp;}return*this;}*//*//赋值运算符重载现代写法String&operator=(constString&s){if(this!=&s){Stringtmp(s._pStr);std::swap(_pStr,tmp._pStr);}return*this;}*///赋值运算符重载现代写法String&operator=(Strings){swap(_pStr,s._pStr);return*this;}~String(){if(_pStr)delete[]_pStr;}char*C_Str(){return_pStr;}char&operator[](size_tindex){return_pStr[index];}voidPushBack(constchar&ch){/*_CheckCapacity(_size+2);_pStr[_size]=ch;_pStr[++_size]='\0';*/Insert(_size,ch);}voidPopBack(){assert(_size>0);--_size;_pStr[_size]='\0';}voidInsert(size_tpos,charch){assert(pos<=_size);_CheckCapacity(_size+2);size_tcur=_size;while(cur>=pos){_pStr[cur+1]=_pStr[cur];cur--;}_pStr[pos]=ch;++_size;}voidInsert(intpos,constchar*str){assert(pos>=0&&pos<=_size);//增容size_tsize=strlen(str);_CheckCapacity(_size+1+size);//挪动数据intindex=_size;while(index>=pos){_pStr[index+size]=_pStr[index];--index;}//拷贝for(size_ti=0;i<size;++i){_pStr[pos++]=str[i];}_size+=size;}intFind(charch){for(size_tindex=0;index<_size;++index){if(_pStr[index]=ch){returnindex;}}return-1;}intFind(constchar*subStr){assert(subStr);size_tdstIndex=0;//要查找的子串size_tsrcIndex=0;size_tsubSize=strlen(subStr);for(dstIndex=0;dstIndex<=_size-subSize;++dstIndex){for(srcIndex=0;srcIndex<subSize;++srcIndex){if(subStr[srcIndex]!=_pStr[dstIndex+srcIndex]){break;}}if(srcIndex==subSize){returndstIndex;}}return-1;}voidErase(size_tpos){assert(pos<_size);for(size_ti=pos+1;i<=_size;++i){_pStr[i-1]=_pStr[i];}--_size;}String&operator+=(constString&s){Insert(_size,s._pStr);return*this;}//Strings("Hello");//可以使用s+=String("World");String("World")->拷贝构造->String&s//也可使用s+="World";"World"->构造函数->String&s//如果改为String&operator+=(String&s)则不能使用s+="World"。例如:/*inti=0;//double&a=i;//i先创建一个临时对象,然后把临时对象给double&a,a就成为一个临时变量的引用。错误constdouble&a=i;//加const,可以引用临时变量。正确*//*Strings1="sssssss";//"sssssss"生成一个匿名对象,匿名对象再构造s1。编译器将两步优化为一步:"sssssss"直接构造s1。//String&s2="sssssss";//不能引用匿名(临时)对象。错误constString&s3="sssssss";//加const,可以引用临时变量。正确*/booloperator==(constString&s){return(strcmp(_pStr,s._pStr)==0);}booloperator>(constString&s){return(strcmp(_pStr,s._pStr)>0);}booloperator>=(constString&s){return(*this>s||*this==s);}booloperator<(constString&s){return!(*this>=s);}booloperator<=(constString&s){return!(*this>s);}protected:void_CheckCapacity(size_tneedSize){if(_size+1>=_capacity){_capacity=_capacity+needSize>2*_capacity?needSize:2*_capacity;_pStr=(char*)realloc(_pStr,_capacity);}}protected:char*_pStr;size_t_size;size_t_capacity;};ostream&operator<<(ostream&_cout,constString&s){_cout<<s._pStr;return_cout;}
推荐文章:
C++面试中string类的一种正确写法:http://coolshell.cn/articles/10478.html
声明:本站所有文章资源内容,如无特殊说明或标注,均为采集网络资源。如若本站内容侵犯了原著者的合法权益,可联系本站删除。