標準庫中的string:C++初階學習第六彈——string(1)——標準庫中的string類-CSDN博客
前言:
在前面我們已經學習了如何使用標準庫中的string類,但作為一個合格的程序員,我們不僅要會用,還要知道如何實現string中的類函數等內容,今天我們就來講解一下string的模擬實現
目錄
一、string類的構造
二、string類的拷貝構造
三、string類的析構函數
四、string類的運算符重載
1、operator=的傳統寫法
2、operator=的現代寫法
五、代碼實例
六、總結
string的模擬實現中最重要的就是string類的構造、拷貝構造、賦值運算符重載以及析構函數
接下來我們就圍繞這些重點進行學習
一、string類的構造
首先我們要清楚string類在底層實際上就是一個字符指針和許多類函數,所以它的類成員變量就是:
private:char* _str;
我們先把模擬構造給出來再來講解:
//為了區分標準庫,我們用String
class String
{
public:String(const char* str = ""){if (str == nullptr){assert(false);return;}_str = new char[strlen(str) + 1];strcpy(_str, str);}void String_print(){cout << _str << endl;}
private:char* _str;
};
int main()
{String s1("abc");s1.String_print();return 0;
}
運行結果:
相信一定有細心的朋友已經注意到我們在給參數時并沒有給任何東西,原因如下:
還有一點需要注意的是:我們在賦值時是創建一個新空間來儲存,并不是直接賦值,這就涉及深拷貝的問題了,在下面我們講拷貝構造的時候能更清晰的體現出來
二、string類的拷貝構造
模擬實現的代碼如下:
String(const String& s): _str(new char[strlen(s._str) + 1]){strcpy(_str, s._str);}
在這里我們主要來講解一下深拷貝和淺拷貝的問題,我們放在一個完整的代碼實例:
class String
{
public:String(const char* str = ""){if (str == nullptr){assert(false);return;}_str = new char[strlen(str) + 1];strcpy(_str, str);}String(const String& s): _str(new char[strlen(s._str) + 1]){strcpy(_str, s._str);}void String_print(){cout << _str << endl;}
private:char* _str;
};
int main()
{String s1("abc");s1.String_print();String s2(s1);s2.String_print();return 0;
}
運行結果:
錯誤示范:
三、string類的析構函數
由于string類對象不管以哪個方式創建時,都需要用new來開辟空間,所以string的析構函數寫法為:
~String(){if (_str) //檢查一下_str是否為空,如果為空就不用再釋放空間了{delete[] _str;_str = nullptr;}}
四、string類的運算符重載
string類的運算符重載整體來說沒啥難度,在這里我們也不做過多講解,重點來講解一下operator=的兩種寫法
1、operator=的傳統寫法
String& operator=(const String& s){if (s._str != _str){char* ptr = new char[strlen(s._str) + 1]; //+1是因為要多開辟一個空間存放\0strcpy(ptr, s._str);delete _str; //清空_str中可能有的數據_str = ptr;}return *this;}
2、operator=的現代寫法
String& operator=(String s)
{swap(_str, s._str); //swap函數算法庫中存在,所以可以直接使用return *this;
}
單從篇幅上來比較,現代寫法要比傳統寫法精簡的多,那么它們兩個究竟是如何實現它們的功能的呢?我們看下面的分析:
· 傳統寫法:
傳統寫法函數的參數是后值的引用,我們通過創建一個新的字符指針,并開辟空間接受后值,再把這個新創建的指針的地址傳給我們的對象,從而實現了operator=的功能
· 現代寫法:
現代寫法則聰明的使用了算法庫中的swap函數,從而讓函數達到一個很精簡的效果,該函數的參數是后值的臨時拷貝,本來就是深拷貝,所以通過swap交換即可
傳統寫法和現代寫法的過程比較:
五、代碼實例
//為了區分標準庫,我們用String
class String
{
public:String(const char* str = ""){if (str == nullptr){assert(false);return;}_str = new char[strlen(str) + 1];strcpy(_str, str);}String(const String& s): _str(new char[strlen(s._str) + 1]){strcpy(_str, s._str);}//現代寫法String& operator=(String s){swap(_str, s._str);return *this;}傳統寫法//String& operator=(const String& s)//{// if (s._str != _str)// {// char* ptr = new char[strlen(s._str) + 1]; //+1是因為要多開辟一個空間存放\0// strcpy(ptr, s._str);// delete _str; //清空_str中可能有的數據// _str = ptr;// }// return *this;//}void String_print(){cout << _str << endl;}~String(){if (_str) //檢查一下_str是否為空,如果為空就不用再釋放空間了{delete[] _str;_str = nullptr;}}
private:char* _str;
};
int main()
{String s1("abc");s1.String_print();String s2(s1);s2.String_print();String s3 = s2;s3.String_print();return 0;
}
運行結果:
六、總結
以上就是string模擬實現的比較重要的部分,其他類函數我們并沒有寫出來,但難度都不大,感興趣的老鐵可以自己摸索一下或者在網上搜一下它的實現
感謝各位大佬觀看,創作不易,還請一鍵三連!!!