您好,登錄后才能下訂單哦!
這篇文章主要介紹“C++ String部分成員怎么實現”,在日常操作中,相信很多人在C++ String部分成員怎么實現問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”C++ String部分成員怎么實現”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!
class string { private: char* _str; int _size; int _capacity; };
說明:以下的五個成員函數的模擬實現,均去除了_size
和_capacity
成員變量,目的是為了更方便解釋重點。在五個成員函數模擬后,會對string類的設計進行補全。
我們是否可以使用默認構造函數來初始化對象?在這種情況下是萬萬不能的!要記住默認的構造函數對自定義類型會去調用它自己的構造函數進行初始化,而對于內置類型是不做處理的,此時我們的成員變量_str
的類型是內置類型,不會被初始化,所以一定要自己寫構造函數。
//這種構造函數是否可行? string(const char* str) { _str = str; }
這種寫法做不到用字符串構造一個對象。
原因:這樣會使得str
和_str
指向的都是同一塊空間。str會影響到_str.
所以正確的做法是,給_str
分配一塊屬于自己的空間,再把str
的值拷貝給_str.
string(const char* str) { _str = new char[strlen(str) + 1]; //要多給一個'\0'的空間 strcpy(_str, str); }
修一下小細節:
1.實例化對象的時候是支持無參構造的,所以可以給參數一個缺省值""
,里面自己隱藏的有一個\0
.如果沒有傳參數,則使用缺省值。
string(const char* str = "") { _str = new char[strlen(str) + 1]; //要多給一個'\0'的空間 strcpy(_str, str); }
看了普通構造函數的模擬實現以后,最不應該犯的錯就是把一個string對象的數據直接給了另一個string對象
所以直接甩代碼
string(const string& s) { _str = new char[strlen(s._str) + 1]; strcpy(_str, s._str); }
當然,如果有前面所寫普通構造函數,還可以利用普通構造函數來拷貝構造一個對象。
//還可以借助普通構造函數 string(const string& s) :_str(nullptr) { string tmp(s._str); swap(_str, tmp._str); }
這里重載賦值,是為了把一個已經存在的string對象的數據給另一個已經存在的string對象。
也就意味著,兩個對象均有自己的空間。不要把string對象的_str直接賦值,否則析構的時候會析構兩次,并且這兩個string對象由于_str使用的是同一塊空間,會相互之間影響。
string& operator=(const string& s) { delete[] _str; //把原來的空間釋放掉 _str = new char[strlen(s._str) + 1]; //給一塊新的空間 strcpy(_str, s._str);; }
上面這種方法是不行的。
1.不排除自己給自己賦值的情況,自己都給釋放了,拿什么來賦值?
2.使用delete先釋放,只要地址正確無論如何都會釋放成功,但是new
一塊空間不一定會成功,如果一開始就給釋放了,而我去申請空間卻申請不到,那就是不僅沒有賦值成功,還把我自己原本有的給丟了。
//正確的寫法 string& operator=(const string& s) { if (this != &s) { char* tmp = new char[strlen(s._str) + 1]; strcpy(tmp, s._str); delete[] _str; _str = tmp; } return *this; //如果自己給自己賦值,那就返回自己 }
還可以使用傳值的方法
string& operator=(string s) { swap(_str, s._str); return *this; }
~string() { if (_str) { delete[] _str; _str = nullptr; } }
//因為std庫里原本有一個string,所以這里加上一個命名空間,防止命名污染 namespace YDY { class string { public: string(const char* str = "") :_size(strlen(str)) ,_capacity(_size) { _str = new char[_capacity + 1]; //要多給一個'\0'的空間 strcpy(_str, str); } string(const string& s) :_str(nullptr) ,_size(s._size) ,_capacity(s._capacity) { string tmp(s._str); swap(_str, tmp._str); } string& operator=(const string& s) { if (this != &s) { char* tmp = new char[strlen(s._str) + 1]; strcpy(tmp, s._str); delete[] _str; _str = tmp; _size = s._size; _capacity = s._capacity; } return *this; } ~string() { if (_str) { delete[] _str; _str = nullptr; } _size = _capacity = 0; } private: char* _str; int _size; int _capacity; }; void test() { string s1; string s2(s1); string s3 = s1; } }
typedef char* iterator; typedef const char* const_iterator; iterator begin() { return _str; } iterator end() { return _str + _size; } const_iterator begin() const { return _str; } const_iterator end() const { return _str + _size; }
const char* c_str() { return _str; } size_t size() { return _size; } char& operator[](size_t pos) { assert(pos < _size); return _str[pos]; } const char& operator[](size_t pos) const { assert(pos < _size); return _str[pos]; } //reserve void reserve(size_t n) { if (n > _capacity) { //擴容到n+1 //tmp是內置類型, char* tmp = new char[n + 1]; strcpy(tmp, _str); delete[] _str; _str = tmp; _capacity = n; } } // void push_back(char c) { //空間不夠,擴容 if (_size == _capacity) { //擴容 reserve(_size + 1); } _str[_size] = c; _size++; _str[_size] = '\0'; } void append(const char* str) { int len = strlen(str); if (_size + len > _capacity) { //增容 reserve(_size + len); } strcpy(_str + _size, str); _size += len; } string& operator+=(char ch) { push_back(ch); return *this; } string& operator+=(const char* str) { //復用追加函數append() append(str); return *this; } //任意位置的插入 string& insert(size_t pos, char ch) { if (_size == _capacity) { reserve(_size + 1); } //開始插入 int end = _size + 1; //找到pos的位置,并留出pos的位置以便插入 while (end > pos) { _str[end] = _str[end - 1]; end--; } _str[pos] = ch; _size++; return *this; } string& insert(size_t pos, const char* str) { assert(pos < _size); size_t len = strlen(str); if (_size + len > _capacity) { //增容 reserve(_size + len); } //找到pos的位置,并且留出要插入的位置 size_t end = _size + len; while (end > pos) { _str[end] = _str[end - len]; end--; } //開始插入 strncpy(_str + pos, str, len); return *this; } //從pos的位置開始刪除len的長度 string& erase(size_t pos = 0, size_t len = std::string::npos) { assert(pos < _size); if (len == std::string::npos || pos + len > _size) { _str[pos] = '\0'; _size = pos; } else { strcpy(_str + pos, _str + pos + len); _size -= len; } return *this; }
到此,關于“C++ String部分成員怎么實現”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。