C++(12):String型別
阿新 • • 發佈:2021-01-13
一、普通String型別
#include<assert.h> //string型別 class String { char* str; //new FILE *fp thread(要重寫拷貝和賦值,防止出現淺拷貝和淺賦值) String(char* s, int) { str = s; } public: String(const char* s = nullptr) { if (s != nullptr) { int len = strlen(s) + 1; str = new char[len]; strcpy_s(str, len, s); //len是str開闢的空間長度 } else { str = new char[1]; //僅指向一個位元組 this->str[0] = '\0'; //一定讓他不為空,指向指向'\0'的一個空串 //否則賦值,拷貝等,都要考慮四種情況,誰為不為空 //eg:s1 NULL s2 "defe" //this->str = '\0';是將其置為空指標 } } ~String() { if (str != nullptr) { delete[] str; } str = nullptr; } String(const String& s) //淺拷貝 { //str = s.str; //共享資源,共享記憶體空間,會有重複釋放的問題 if (s.str != nullptr) //深拷貝 { int len = strlen(s.str) + 1; str = new char[len]; strcpy_s(str, len, s.str); //len是str開闢的空間長度 } } String& operator = (const String& s) { if (this!= &s) { //str = s.str; //淺賦值 delete[] str; //深賦值 int len = strlen(s.str) + 1; str = new char[len]; strcpy_s(str, len, s.str); } return *this; } //移動構造:是資源的移動(減輕對堆區不斷開闢釋放的過程) String(String&& s) { str = s.str; s.str = nullptr; } //移動賦值 String& operator=(String&& s) { if (this != &s) { delete[] str; str = s.str; s.str = nullptr; } return *this; } String operator+(const String& s) const { int total = strlen(this->str) + strlen(s.str) + 1; char* sp = new char[total]; strcpy_s(sp, total, this->str); strcat_s(sp, total, s.str); //return String(sp) //調動構造產生一個臨時物件,sp指向的空間就沒有釋放掉 return String(sp, 1); //構建的臨時物件的str將指向sp,將此物件賦給s3,資源移動 } //物件+物件 String operator+(const char* s) const //物件+變數 { return *this + String(s); } String& operator+=(const String& s) { char* tmp = this->str; int total = strlen(tmp) + strlen(s.str) + 1; str = new char[total]; strcpy_s(str, total, tmp); strcat_s(str, total, s.str); delete[] tmp; //tmp是原來str指向的資源 return *this; } //s1 += s2 String& operator+=(const char* s) //物件+=變數 { return *this += String(s); } char& operator[] (const int index) const { assert(index >= 0 && index < strlen(this->str)); return str[index]; } const char& operator[] (const int index) const { assert(index >= 0 && index < strlen(this->str)); return str[index]; } ostream& operator<<(ostream& out) const { out << str; return out; } //s1<<cout; s1.operator<<(cout);operator<<(&s1,cout) }; //設為全域性函式,放入類中作為成員函式,引數列表省略了this指標,將變為3個引數 String operator+(const char* s, const String& st) //變數+物件 { return String(s) + st; } String fun() { String tmp("nswubd"); return tmp; } ostream& operator<<(ostream& out, const String& s) { s << cout; return cout; } int main() { //String s1("wejbfwue"); //String s2("dneide"); //String s3(s1); String s1 = fun(); //構建的臨時物件就是s1,移動賦值 String s2("tulun"); s2 = fun(); //深拷貝,tmp賦給臨時物件,析構掉tmp,把臨時物件賦給s2,把臨時物件的資源給s2 String s1("dheudh"); s1 = std::move(s2); //當沒寫賦值語句時,預設的移動賦值(不好用,要重寫):是將字串拷貝到s1所指向的空間,不會刪除s2的資源,將內容直接拷貝 String s4("wbfuwf"); String s5("ejiwdewdw"); s4 = s5; //呼叫普通的賦值語句,因為s5有名字,不能進行右值引用 String s6; //s6中放的是‘\0’ s6 = s4 + s5; s4 += s5; cout << s1 << endl; //輸出 return 0; }
寫賦值函式時都要考慮四種情況:
not not
not nullptr
nullptr not
nullptr nullptr
二、字元陣列為柔性陣列的String
class String { //柔性陣列 struct StrNode { int len; //字串的長度 int size; //字串的空間大小 int ref; //引用計數 char data[]; //柔性陣列, 定義在最後 }; private: StrNode* str; String(StrNode* s) { str = s; } public: String(const char* s = nullptr): str(nullptr) { if (s != nullptr) { int len = strlen(s) + 1; str = (StrNode*)malloc(sizeof(StrNode) + 2 * len); if (str == nullptr) exit(EXIT_FAILURE); str->len = len; str->size = 2 * len; str->ref = 1; strcpy_s(str->data, 2 * len, s); } } ~String() { if (str != nullptr && -- this->str->ref == 0) { free(this->str); } str = nullptr; } String(const String& s) :str(s.str) { if (str != nullptr) { str->ref += 1; } } String& operator=(const String& s) { if (this != &s) { if (str != nullptr && --str->ref == 0) { free(str); } str = s.str; if(str != nullptr) { str->ref += 1; } } return *this; } //s1 =s2(四種情況) //移動 String(String&& s) { if (str != nullptr && --str->ref == 0) { free(str); } str = s.str; s.str = nullptr; } String& operator=(String&& s) { if (this != &s) { if (str != nullptr && --str->ref == 0) { free(str); } str = s.str; s.str = nullptr; } return *this; } String operator+(const String& s) const { //先開size int total = 1; if (str != nullptr) total += str->len; if (s.str != nullptr) total += s.str->len; StrNode* sp = (StrNode*)malloc(sizeof(StrNode) + 2 * total); if (sp == nullptr) exit(EXIT_FAILURE); if (str != nullptr) strcpy_s(sp->data, 2 * total, str->data); if (s.str != nullptr) strcat_s(sp->data, 2 * total, s.str->data); //設定StrNode的變數的值 sp->len = total - 1; sp->size = 2 * total; str->ref = 1; return String(sp); } //四種情況 }; int main() { String s1("iewbd"); String s2("iewbciwebc"); String s3; String s4(s1); String s5(s2); s3 = s1 + s2; //s3 = s1 + "neonwoi"; //s3 = "oenw" + s1; s1 += s2; //s1 += "iedi"; return; }