您好,登錄后才能下訂單哦!
string類是C++的一個常見的面試題,考查面試者的基本功,雖然簡單,但是有很多細節需要注意。
#pragma once #include <assert.h> /* 深拷貝與淺拷貝: 淺拷貝,只是對指針的拷貝,拷貝后兩個指針指向同一個內存空間,深拷貝不但對指針進行拷貝, 而且對指針指向的內容進行拷貝,經深拷貝后的指針是指向兩個不同地址的指針。淺拷貝是指源對象 與拷貝對象共用一份實體,僅僅是引用的變量不同(名稱不同)。對其中任何一個對象的改動都會影響另外一個對象。 深拷貝是指源對象與拷貝對象互相獨立,其中任何一個對象的改動都不會對另外一個對象造成影響。 舉個例子,一個人名叫張三,后來用他克隆(假設法律允許)了另外一個人,叫李四,不管是張三缺胳膊少腿 還是李四缺胳膊少腿都不會影響另外一個人。 */ class String { friend ostream& operator<<(ostream& _cout, const String& s); public: /* String() :_pStr(/ *new char('\0')* /new char[1]) { _pStr[0] = '\0'; //不能是"\0" } //new和delete,new[]和delete[]一定要匹配使用 //strlen 不能傳NULL String(char* pStr) :_pStr(new char[strlen(pStr)+1]) { strcpy(_pStr, pStr); //strcpy會拷貝'\0'過去 } */ //構造函數合并 String(char* pStr = "") { _size = strlen(pStr); _capacity = _size+1; _pStr = new char[_size+1]; strcpy(_pStr, pStr); } /* //拷貝構造函數常規寫法 String(const String& s) :_pStr(new char[strlen(s._pStr)+1]) { strcpy(_pStr, s._pStr); } */ String(const String& s) :_pStr(NULL) //需要先將this->_pStr置為空,否則交換后tmp為隨機值,析構tmp時delete[]出現錯誤 { String tmp(s._pStr); std::swap(_pStr, tmp._pStr); } /* //賦值運算符重載常規寫法 -> 釋放原來的空間,開辟和s一樣大的空間 String& operator=(const String& s) { if (this != &s) { / * //存在一致性問題。如果new空間失敗,原來的空間將被釋放,深拷貝失敗 delete[] _pStr; _str = new char[strlen(s._pStr)+1]; strcpy(_pStr, s._pStr); * / //先開辟空間,再拷貝 char* tmp = new char[strlen(s._pStr)+1]; strcpy(tmp, s._pStr); delete[] _pStr; _pStr = tmp; } return *this; } */ /* //賦值運算符重載現代寫法 String& operator=(const String& s) { if (this != &s) { String tmp(s._pStr); std::swap(_pStr, tmp._pStr); } return *this; } */ //賦值運算符重載現代寫法 String& operator=(String s) { swap(_pStr, s._pStr); return *this; } ~String() { if (_pStr) delete[] _pStr; } char* C_Str() { return _pStr; } char& operator[](size_t index) { return _pStr[index]; } void PushBack(const char& ch) { /*_CheckCapacity(_size + 2); _pStr[_size] = ch; _pStr[++_size] = '\0';*/ Insert(_size, ch); } void PopBack() { assert(_size > 0); --_size; _pStr[_size] = '\0'; } void Insert(size_t pos, char ch) { assert(pos <= _size); _CheckCapacity(_size + 2); size_t cur = _size; while (cur >= pos) { _pStr[cur+1] = _pStr[cur]; cur--; } _pStr[pos] = ch; ++_size; } void Insert(int pos, const char* str) { assert(pos>=0 && pos <= _size); //增容 size_t size = strlen(str); _CheckCapacity(_size+1+size); //挪動數據 int index = _size; while (index >= pos) { _pStr[index+size] = _pStr[index]; --index; } //拷貝 for (size_t i = 0; i < size; ++i) { _pStr[pos++] = str[i]; } _size += size; } int Find(char ch) { for (size_t index = 0; index < _size; ++index) { if (_pStr[index] = ch) { return index; } } return -1; } int Find(const char* subStr) { assert(subStr); size_t dstIndex = 0; //要查找的子串 size_t srcIndex = 0; size_t subSize = strlen(subStr); for (dstIndex = 0; dstIndex <= _size - subSize; ++dstIndex) { for (srcIndex = 0; srcIndex < subSize; ++srcIndex) { if (subStr[srcIndex] != _pStr[dstIndex+srcIndex]) { break; } } if (srcIndex == subSize) { return dstIndex; } } return -1; } void Erase(size_t pos) { assert(pos < _size); for (size_t i = pos+1; i <= _size; ++i) { _pStr[i-1] = _pStr[i]; } --_size; } String& operator+=(const String& s) { Insert(_size, s._pStr); return *this; } //String s("Hello"); //可以使用 s += String(" World"); String(" World") -> 拷貝構造 -> String& s //也可使用 s += " World"; " World" -> 構造函數 -> String& s //如果改為String& operator+=(String& s)則不能使用 s += " World"。 例如: /* int i = 0; //double& a = i; //i先創建一個臨時對象,然后把臨時對象給double& a,a就成為一個臨時變量的引用。錯誤 const double& a = i; //加const,可以引用臨時變量。正確 */ /* String s1 = "sssssss"; //"sssssss"生成一個匿名對象,匿名對象再構造s1。編譯器將兩步優化為一步:"sssssss"直接構造s1。 //String& s2 = "sssssss"; //不能引用匿名(臨時)對象。錯誤 const String& s3 = "sssssss"; //加const,可以引用臨時變量。正確 */ bool operator==(const String& s) { return (strcmp(_pStr, s._pStr) == 0); } bool operator>(const String& s) { return (strcmp(_pStr, s._pStr) > 0); } bool operator>=(const String& s) { return (*this > s || *this == s); } bool operator<(const String& s) { return !(*this >= s); } bool operator<=(const String& s) { return !(*this > s); } protected: void _CheckCapacity(size_t needSize) { if (_size+1 >= _capacity) { _capacity = _capacity+needSize > 2*_capacity ? needSize : 2*_capacity; _pStr = (char*)realloc(_pStr, _capacity); } } protected: char* _pStr; size_t _size; size_t _capacity; }; ostream& operator<<(ostream& _cout, const String& s) { _cout<<s._pStr; return _cout; }
推薦文章:
C++面試中string類的一種正確寫法:http://coolshell.cn/articles/10478.html
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。