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)"<= _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<
實現了深拷貝的方法那仫有沒有更加高效的方法呢?當然,那就是寫時拷貝,我們發現在上述深拷貝的版本裡實現的拷貝構造函數又為新的對象重新開辟空間(防止淺拷貝的後遺症:淺拷貝是值拷貝使得兩個指針指向同一塊空間,在析構該空間時對同一塊空間釋放多次就會出現問題),那仫如果我們繼承了淺拷貝的後遺症-就讓多個指針指向同一塊空間,此時我們只需要設置一個指針變量讓它記錄指向這塊空間的指針個數,在析構時只要該指針變量的內容為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<<"構造"<= 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<<"析構"<
在這裡我們將指針指向的計數器的位置放置在數據空間的前四個字節處
測試用例:
void test1()
{
String str1("abcd");
cout<