C++中sting類的簡(jiǎn)單實(shí)現(xiàn)方法
String
在C++的學(xué)習(xí)生涯我中發(fā)現(xiàn)String類的功能十分強(qiáng)大,所以我們是很有必要模擬實(shí)現(xiàn)它的,況且在面試的時(shí)候模擬實(shí)現(xiàn)一個(gè)String類也是面試官經(jīng)常會(huì)考的,但是因?yàn)橥饨缫蛩氐南拗莆覀兪遣豢赡苣M的和庫(kù)里的string一致的(C++庫(kù)里的string功能更強(qiáng)大),所以今天我們只模擬實(shí)現(xiàn)string的基本功能-構(gòu)造函數(shù),拷貝構(gòu)造函數(shù),析構(gòu)函數(shù),賦值運(yùn)算符重載,運(yùn)算符+=的重載,運(yùn)算符[]的重載,c_str(得到一個(gè)C風(fēng)格的字符指針,可操作字符串),Size,Push_Back,Insert(深拷貝),以及用寫時(shí)拷貝copy_on_write的方式實(shí)現(xiàn)基本的String類
深拷貝的方式
class String
{
friend ostream &operator<<(ostream &os,String &s);
public:
String(const char *str=""); //全缺省的構(gòu)造函數(shù),解決空字符串的問(wèn)題
String(const String &ps); //深拷貝
String &operator=(String s);
String &operator+=(const char * s);
const char *C_Str()const //得到C風(fēng)格的字符指針
{
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;
}
通過(guò)測(cè)試上述代碼可正常運(yùn)行,特別是在實(shí)現(xiàn)賦值運(yùn)算符重載的時(shí)候我們使用了兩種方式,值得一提的是應(yīng)用swap函數(shù)來(lái)實(shí)現(xiàn)賦值運(yùn)算符的重載(在傳參時(shí)不可以傳引用),因?yàn)閼?yīng)用swap函數(shù)實(shí)現(xiàn)是根據(jù)臨時(shí)變量的創(chuàng)建并且該臨時(shí)變量出作用域就會(huì)自動(dòng)調(diào)用析構(gòu)函數(shù)銷毀(現(xiàn)代的方法)
測(cè)試深拷貝的方法
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;
}
實(shí)現(xiàn)了深拷貝的方法那仫有沒(méi)有更加高效的方法呢?當(dāng)然,那就是寫時(shí)拷貝,我們發(fā)現(xiàn)在上述深拷貝的版本里實(shí)現(xiàn)的拷貝構(gòu)造函數(shù)又為新的對(duì)象重新開辟空間(防止淺拷貝的后遺癥:淺拷貝是值拷貝使得兩個(gè)指針指向同一塊空間,在析構(gòu)該空間時(shí)對(duì)同一塊空間釋放多次就會(huì)出現(xiàn)問(wèn)題),那仫如果我們繼承了淺拷貝的后遺癥-就讓多個(gè)指針指向同一塊空間,此時(shí)我們只需要設(shè)置一個(gè)指針變量讓它記錄指向這塊空間的指針個(gè)數(shù),在析構(gòu)時(shí)只要該指針變量的內(nèi)容為1我們就釋放這塊空間否則就讓計(jì)數(shù)器減1,這就是寫時(shí)拷貝的主要思想,下面就讓我們用寫時(shí)拷貝的方法實(shí)現(xiàn)一個(gè)簡(jiǎn)單的String類吧
寫時(shí)拷貝的方法
//寫時(shí)拷貝的方式
class String
{
friend ostream& operator<<(ostream & os,String &s);
public:
String(const char *str="")
:_str(new char[strlen(str)+1+4])
{
cout<<"構(gòu)造"<<endl;
_str+=4;
*((int *)(_str-4))=1;
strcpy(_str,str);
}
String(String &s)
{
cout<<"拷貝構(gòu)造"<<endl;
++*((int *)(s._str-4));
_str=s._str;
}
String &operator=(const String &s)
{
cout<<"賦值語(yǔ)句"<<endl;
if(--*(int *)(_str-4) == 0)
{
delete[](_str-4);
}
++(*(int *)(s._str-4));
_str=s._str;
return *this;
}
char &operator[](int index) //寫時(shí)拷貝
{
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<<"析構(gòu)"<<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;
}
在這里我們將指針指向的計(jì)數(shù)器的位置放置在數(shù)據(jù)空間的前四個(gè)字節(jié)處
測(cè)試用例:
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類的簡(jiǎn)單實(shí)現(xiàn)方法,希望對(duì)大家有所幫助,如果大家有任何疑問(wèn)請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!
- 關(guān)于C++ string和c類型字符數(shù)組的對(duì)比
- 從string類的實(shí)現(xiàn)看C++類的四大函數(shù)(面試常見)
- 詳解C++中StringBuilder類的實(shí)現(xiàn)及其性能優(yōu)化
- c++ String去除頭尾空格的方法
- C++實(shí)現(xiàn)string存取二進(jìn)制數(shù)據(jù)的方法
- 利用C++實(shí)現(xiàn)從std::string類型到bool型的轉(zhuǎn)換
- C++如何通過(guò)ostringstream實(shí)現(xiàn)任意類型轉(zhuǎn)string
- 用標(biāo)準(zhǔn)c++實(shí)現(xiàn)string與各種類型之間的轉(zhuǎn)換
- C字符串與C++中string的區(qū)別詳解
- c++中的string常用函數(shù)用法總結(jié)
- c++中string類成員函數(shù)c_str()的用法
相關(guān)文章
C語(yǔ)言實(shí)現(xiàn)內(nèi)存函數(shù)的示例代碼
本文主要介紹了C語(yǔ)言實(shí)現(xiàn)內(nèi)存函數(shù)的示例代碼,包括memcpy、memmove、memset和memcmp的使用,具有一定的參考價(jià)值,感興趣的可以了解一下2025-02-02
C語(yǔ)言設(shè)計(jì)前中后隊(duì)列實(shí)例代碼
隊(duì)列最主要的作用就是用來(lái)管理數(shù)據(jù)流的,防止數(shù)據(jù)因?yàn)閭鬏旑l率過(guò)快得不到及時(shí)處理而丟失,下面這篇文章主要給大家介紹了關(guān)于C語(yǔ)言設(shè)計(jì)前中后隊(duì)列的相關(guān)資料,需要的朋友可以參考下2021-12-12
OpenMP task construct 實(shí)現(xiàn)原理及源碼示例解析
這篇文章主要為大家介紹了OpenMP task construct 實(shí)現(xiàn)原理及源碼示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-03-03
C語(yǔ)言一個(gè)函數(shù)如何實(shí)現(xiàn)好幾個(gè)return返回值
本文主要介紹了C語(yǔ)言一個(gè)函數(shù)如何實(shí)現(xiàn)好幾個(gè)return返回值,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-08-08
C++函數(shù)對(duì)象Functor與匿名函數(shù)對(duì)象Lambda表達(dá)式詳解
這篇文章主要介紹了C++函數(shù)對(duì)象Functor(仿函數(shù))與匿名函數(shù)對(duì)象(Lambda表達(dá)式)詳細(xì)介紹以及底層實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-08-08
C語(yǔ)言中利用封裝好的函數(shù)實(shí)現(xiàn)英文字母的大小寫轉(zhuǎn)換
這篇文章主要介紹了C語(yǔ)言中利用封裝好的函數(shù)實(shí)現(xiàn)英文字母的大小寫轉(zhuǎn)換,需要的朋友可以參考下2017-10-10
C語(yǔ)言實(shí)現(xiàn)學(xué)生檔案管理系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)學(xué)生檔案管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-05-05

