C++中sting類的簡略完成辦法。本站提示廣大學習愛好者:(C++中sting類的簡略完成辦法)文章只能為提供參考,不一定能成為您想要的結果。以下是C++中sting類的簡略完成辦法正文
String
在C++的進修生活我中發明String類的功效非常壯大,所以我們是很有需要模仿完成它的,何況在面試的時刻模仿完成一個String類也是面試官常常會考的,然則由於外界身分的限制我們是弗成能模仿的和庫裡的string分歧的(C++庫裡的string功效更壯大),所以明天我們只模仿完成string的根本功效-結構函數,拷貝結構函數,析構函數,賦值運算符重載,運算符+=的重載,運算符[]的重載,c_str(獲得一個C作風的字符指針,可操作字符串),Size,Push_Back,Insert(深拷貝),和用寫時拷貝copy_on_write的方法完成根本的String類
深拷貝的方法
class String
{
friend ostream &operator<<(ostream &os,String &s);
public:
String(const char *str=""); //全缺省的結構函數,處理空字符串的成績
String(const String &ps); //深拷貝
String &operator=(String s);
String &operator+=(const char * s);
const char *C_Str()const //獲得C作風的字符指針
{
return _pstr;
}
char &operator[](size_t index)
{
return _pstr[index];
}
size_t Size()const
{
return _size;
}
void PushBack(char c);
String &Insert(size_t pos,const char *str);
//String &operator=(String &s)
//{
// cout<<"String &operator=(String &s)"<<endl;
// if(this != &s)
// {
// delete[]_pstr;
// _pstr=new char[strlen(s._pstr)+1];
// strcpy(_pstr,s._pstr);
// }
// return *this;
//}
~String()
{
cout<<"~String()"<<endl;
if(_pstr != NULL)
{
delete[]_pstr;
_pstr=NULL;
_size=0;
_capacity=0;
}
}
private:
void CheckCapacity(int count);
private:
int _size;
int _capacity;
char *_pstr;
};
ostream &operator<<(ostream &os,String &s)
{
os<<s._pstr;
return os;
}
String::String(const char *str)
:_size(strlen(str))
,_capacity(strlen(str)+1)
,_pstr(new char[_capacity])
{
cout<<"String()"<<endl;
strcpy(_pstr,str);
}
String::String(const String &ps)
:_size(ps._size)
,_capacity(strlen(ps._pstr)+1)
,_pstr(new char[_capacity])
{
cout<<"String(const String &ps)"<<endl;
strcpy(_pstr,ps._pstr);
}
String &String::operator=(String s)
{
cout<<"String &operator=(String s)"<<endl;
std::swap(_pstr,s._pstr);
std::swap(_size,s._size);
std::swap(_capacity,s._capacity);
return *this;
}
void String::CheckCapacity(int count)
{
if(_size+count >= _capacity)
{
int _count=(2*_capacity)>(_capacity+count)?(2*_capacity):(_capacity+count);
char *tmp=new char[_count];
strcpy(tmp,_pstr);
delete[]_pstr;
_pstr=tmp;
_capacity=_count;
}
}
void String::PushBack(char c)
{
CheckCapacity(1);
_pstr[_size++]=c;
_pstr[_size]='\0';
}
String &String::operator+=(const char * s)
{
CheckCapacity(strlen(s));
while(*s)
{
_pstr[_size++]=*s;
s++;
}
_pstr[_size]='\0';
return *this;
}
String &String::Insert(size_t pos,const char *str)
{
char *tmp=new char[strlen(_pstr+pos)];
strcpy(tmp,_pstr+pos);
CheckCapacity(strlen(str));
while(*str)
{
_pstr[pos++]=*str;
str++;
}
strcpy(_pstr+pos,tmp);
return *this;
}
經由過程測試上述代碼可正常運轉,特殊是在完成賦值運算符重載的時刻我們應用了兩種方法,值得一提的是運用swap函數來完成賦值運算符的重載(在傳參時弗成以傳援用),由於運用swap函數完成是依據暫時變量的創立而且該暫時變量出感化域就會主動挪用析構函數燒毀(古代的辦法)
測試深拷貝的辦法
void text1()
{
String str1("hello");
String str2(str1);
String str3;
str3=str1;
cout<<str1<<endl;
cout<<str2<<endl;
cout<<str3<<endl;
cout<<strlen(str1.C_Str())<<endl; //5
str1[4]='w';
cout<<str1<<endl; //hellw
}
void text2()
{
String str1("abcd");
cout<<str1<<endl;
str1.PushBack('e');
str1.PushBack('f');
str1.PushBack('g');
str1.PushBack('h');
str1.PushBack('i');
cout<<str1<<endl;
cout<<str1.Size()<<endl;
}
void text3()
{
String str1("hello");
String str2("hello world");
String str3(str2);
str1+=" ";
str1+="world";
cout<<str1<<endl;
str2.Insert(6," abc ");
cout<<str2<<endl;
}
完成了深拷貝的辦法那仫有無加倍高效的辦法呢?固然,那就是寫時拷貝,我們發明在上述深拷貝的版本裡完成的拷貝結構函數又為新的對象從新開拓空間(避免淺拷貝的後遺症:淺拷貝是值拷貝使得兩個指針指向統一塊空間,在析構該空間時對統一塊空間釋放屢次就會湧現成績),那仫假如我們繼續了淺拷貝的後遺症-就讓多個指針指向統一塊空間,此時我們只須要設置一個指針變量讓它記載指向這塊空間的指針個數,在析構時只需該指針變量的內容為1我們就釋放這塊空間不然就讓計數器減1,這就是寫時拷貝的重要思惟,上面就讓我們用寫時拷貝的辦法完成一個簡略的String類吧
寫時拷貝的辦法
//寫時拷貝的方法
class String
{
friend ostream& operator<<(ostream & os,String &s);
public:
String(const char *str="")
:_str(new char[strlen(str)+1+4])
{
cout<<"結構"<<endl;
_str+=4;
*((int *)(_str-4))=1;
strcpy(_str,str);
}
String(String &s)
{
cout<<"拷貝結構"<<endl;
++*((int *)(s._str-4));
_str=s._str;
}
String &operator=(const String &s)
{
cout<<"賦值語句"<<endl;
if(--*(int *)(_str-4) == 0)
{
delete[](_str-4);
}
++(*(int *)(s._str-4));
_str=s._str;
return *this;
}
char &operator[](int index) //寫時拷貝
{
assert(index >= 0 && index < (int)strlen(_str));
if(*(int *)(_str-4) > 1)
{
--*(int *)(_str-4);
char *tmp=new char[strlen(_str)+5];
strcpy(tmp+4,_str);
delete[](_str-4);
_str=tmp+4;
*(int *)(_str-4)=1;
}
return _str[index];
}
~String()
{
cout<<"析構"<<endl;
if(--*(int *)(_str-4) == 0)
{
cout<<"釋放"<<endl;
delete[](_str-4);
}
}
private:
char *_str;
};
ostream& operator<<(ostream &os,String &s)
{
os<<s._str;
return os;
}
在這裡我們將指針指向的計數器的地位放置在數據空間的前四個字節處
測試用例:
void test1()
{
String str1("abcd");
cout<<str1<<endl;
String str2(str1);
cout<<str2<<endl;
String str3;
str3=str1;
cout<<str3<<endl;
}
void test2()
{
String str1("abcd");
cout<<str1<<endl;
String str2;
str2=str1;
cout<<str2<<endl;
str2[2]='w';
cout<<str2<<endl;
}
以上所述是小編給年夜家引見的C++中sting類的簡略完成辦法,願望對年夜家有所贊助,假如年夜家有任何疑問請給我留言,小編會實時答復年夜家的。在此也異常感激年夜家對網站的支撐!