1.所需要的头文件#define _CRT_SECURE_NO_WARNINGS #includeiostream #includestring.h // #includecstring // #includecmath #includestring #includeassert.h using namespace std;2.类中所需要的私有属性引用计数字符串长度内容长度字符串内容通过pstr指针指向using namespace std; class MyString { public: static const size_t STRLEN 32;// private: struct StrNode { int ref;//引用计数 int len;//字符串长度 int capa;//内容长度 char data[];//字符串内容 }; private: StrNode* pstr;3创建pstr指针所需要的空间来保存柔性数组及其属性这里strnode结构体空间内存为12字节柔性数组并没有占位置另外再创建data数组时若所需要的位置以32字节为分界线static StrNode* getNode(size_t len) { len (len STRLEN) ? len : STRLEN; //32 size_t total sizeof(StrNode) sizeof(char) * len; StrNode* newnode (StrNode*)malloc(sizeof(char) * total); if (nullptr newnode) { exit(EXIT_FAILURE); } memset(newnode, 0, sizeof(char) * total); newnode-capa len - 1; return newnode; }4释放结构体指针这里当引用计数为0时析构函数调用static void FreeNode(StrNode* p) { free(p); }5销毁函数在判断无人引用和pstr指向空时调用freevoid destroy() { if (pstr ! nullptr --pstr-ref 0) { FreeNode(pstr); } pstr nullptr; }6.交换函数在赋值运算重载函数和移动赋值运算重载的函数中用到void swap(MyString s) { std::swap(this-pstr, s.pstr); }7这里为基础的构造函数和析构函数不多叙述拷贝构造函数细讲当用到工业级别的对象拷贝如果按照深拷贝构造会造成堆空间不足用浅拷贝引用计数可以解决问题每个对象pstr指针指向的堆空间的位置相同MyString(const char* sp nullptr) :pstr(nullptr)//构造函数 { if (sp ! nullptr *sp ! \0) { int len strlen(sp); pstr getNode(len 1); pstr-ref 1; pstr-len len; strcpy(pstr-data, sp); } } ~MyString() { destroy(); } MyString(const MyString st) :pstr(st.pstr)//浅拷贝 { if (pstr ! nullptr) { pstr-ref 1; } }8移动构造函数和拷贝赋值函数这里拷贝赋值采用了两种代码细讲采用swap函数首先先创建不具名对象临时值tmp启动拷贝构造函数s2的ref1tmp和s1进行交换当代码语段结束tmp析构s1的ref-1实现了拷贝构造函数MyString(MyString st) :pstr(st.pstr)//移动构造函数 { st.pstr nullptr; } MyString operator(const MyString st)//拷贝赋值 { if(thisst) return *this; // // this-destroy(); // pstr st.pstr; // if(pstr!nullptr) // pstr-ref; MyString(st).swap(*this);//构建了不具名对象实现拷贝构造 return *this; }9移动赋值运算重载函数与上述大致相同其核心是为了让s1的ref-1s2不变所有这里创建tmp时要采用移动拷贝构造MyString operator(MyString st)//移动赋值 { if (thisst) return *this; this-destroy(); this-pstr st.pstr; st.pstr nullptr; /* if (this st) return *this; MyString(std::move(st)).swap(*this);*///构建了不具名对象实现拷贝构造 return *this; }10访问指定元素带边界检查const char at(const int index) const { assert(pstr ! nullptr); assert(index 0 index pstr-len); return pstr-data[index]; }11扩容函数创建一个新的空间空间大小为要插入的字符量原字符串大小再将源字符串赋值过来ref设置为1static void InSize( MyString s, size_t size)//扩充函数其他信息不变 { StrNode* newnode getNode(size 1); newnode-ref 1; newnode-len s.pstr-len; memmove(newnode-data, s.pstr-data, s.pstr-len); newnode-data[newnode-len] \0; s.destroy(); s.pstr newnode; }12链接函数先做判断原字符串是否为空若为空创建新字符串开辟空间如若源字符串持有者为1则进行销毁源字符串开辟新的ref1时进行扩容并且加上需求所要的字符MyString append(const size_t count, char x) //stra.append(12, x); { if (this-pstr nullptr) { pstr getNode(count 1); memset(pstr-data, x, count); pstr-len count; pstr-ref 1; pstr-data[pstr-len] \0; } else if (pstr-ref 1) { if (pstr-capa - pstr-len count) { InSize(*this, pstr-capa count); } } else { pstr-ref--; StrNode* p getNode(pstr-lencount1); strcpy(p-data, pstr-data); p-ref 1; p-len pstr-len; pstr p; } memset(pstr-data pstr-len, x, count); pstr-len count; pstr-data[pstr-len] \0; return *this; }
C++:stl库的Mystring仿写
1.所需要的头文件#define _CRT_SECURE_NO_WARNINGS #includeiostream #includestring.h // #includecstring // #includecmath #includestring #includeassert.h using namespace std;2.类中所需要的私有属性引用计数字符串长度内容长度字符串内容通过pstr指针指向using namespace std; class MyString { public: static const size_t STRLEN 32;// private: struct StrNode { int ref;//引用计数 int len;//字符串长度 int capa;//内容长度 char data[];//字符串内容 }; private: StrNode* pstr;3创建pstr指针所需要的空间来保存柔性数组及其属性这里strnode结构体空间内存为12字节柔性数组并没有占位置另外再创建data数组时若所需要的位置以32字节为分界线static StrNode* getNode(size_t len) { len (len STRLEN) ? len : STRLEN; //32 size_t total sizeof(StrNode) sizeof(char) * len; StrNode* newnode (StrNode*)malloc(sizeof(char) * total); if (nullptr newnode) { exit(EXIT_FAILURE); } memset(newnode, 0, sizeof(char) * total); newnode-capa len - 1; return newnode; }4释放结构体指针这里当引用计数为0时析构函数调用static void FreeNode(StrNode* p) { free(p); }5销毁函数在判断无人引用和pstr指向空时调用freevoid destroy() { if (pstr ! nullptr --pstr-ref 0) { FreeNode(pstr); } pstr nullptr; }6.交换函数在赋值运算重载函数和移动赋值运算重载的函数中用到void swap(MyString s) { std::swap(this-pstr, s.pstr); }7这里为基础的构造函数和析构函数不多叙述拷贝构造函数细讲当用到工业级别的对象拷贝如果按照深拷贝构造会造成堆空间不足用浅拷贝引用计数可以解决问题每个对象pstr指针指向的堆空间的位置相同MyString(const char* sp nullptr) :pstr(nullptr)//构造函数 { if (sp ! nullptr *sp ! \0) { int len strlen(sp); pstr getNode(len 1); pstr-ref 1; pstr-len len; strcpy(pstr-data, sp); } } ~MyString() { destroy(); } MyString(const MyString st) :pstr(st.pstr)//浅拷贝 { if (pstr ! nullptr) { pstr-ref 1; } }8移动构造函数和拷贝赋值函数这里拷贝赋值采用了两种代码细讲采用swap函数首先先创建不具名对象临时值tmp启动拷贝构造函数s2的ref1tmp和s1进行交换当代码语段结束tmp析构s1的ref-1实现了拷贝构造函数MyString(MyString st) :pstr(st.pstr)//移动构造函数 { st.pstr nullptr; } MyString operator(const MyString st)//拷贝赋值 { if(thisst) return *this; // // this-destroy(); // pstr st.pstr; // if(pstr!nullptr) // pstr-ref; MyString(st).swap(*this);//构建了不具名对象实现拷贝构造 return *this; }9移动赋值运算重载函数与上述大致相同其核心是为了让s1的ref-1s2不变所有这里创建tmp时要采用移动拷贝构造MyString operator(MyString st)//移动赋值 { if (thisst) return *this; this-destroy(); this-pstr st.pstr; st.pstr nullptr; /* if (this st) return *this; MyString(std::move(st)).swap(*this);*///构建了不具名对象实现拷贝构造 return *this; }10访问指定元素带边界检查const char at(const int index) const { assert(pstr ! nullptr); assert(index 0 index pstr-len); return pstr-data[index]; }11扩容函数创建一个新的空间空间大小为要插入的字符量原字符串大小再将源字符串赋值过来ref设置为1static void InSize( MyString s, size_t size)//扩充函数其他信息不变 { StrNode* newnode getNode(size 1); newnode-ref 1; newnode-len s.pstr-len; memmove(newnode-data, s.pstr-data, s.pstr-len); newnode-data[newnode-len] \0; s.destroy(); s.pstr newnode; }12链接函数先做判断原字符串是否为空若为空创建新字符串开辟空间如若源字符串持有者为1则进行销毁源字符串开辟新的ref1时进行扩容并且加上需求所要的字符MyString append(const size_t count, char x) //stra.append(12, x); { if (this-pstr nullptr) { pstr getNode(count 1); memset(pstr-data, x, count); pstr-len count; pstr-ref 1; pstr-data[pstr-len] \0; } else if (pstr-ref 1) { if (pstr-capa - pstr-len count) { InSize(*this, pstr-capa count); } } else { pstr-ref--; StrNode* p getNode(pstr-lencount1); strcpy(p-data, pstr-data); p-ref 1; p-len pstr-len; pstr p; } memset(pstr-data pstr-len, x, count); pstr-len count; pstr-data[pstr-len] \0; return *this; }