自定义实现字符串string的接口
2018-06-17 22:10:17来源:未知 阅读 ()
用char*管理String类的内存,new动态分配,在析构函数中delete char*指向的new出来的内存,一个string类需要实现那些接口可参考标准库里的string: http://www.cplusplus.com/reference/string/string/
- 实现思路是:在创建String、String需要伸缩(如赋值时需要调整大小、字符串相加也需要更大的空间)时重新new内存,并释放掉原有内存;标准库string的空间是预先分配的,有多余的空间可用,如果string需要伸缩,就开辟新的内存空间。
- >>重载的思路是:用cin.getline来读取标准输入到字符指针指向的空间——空间有个预设的大小,如100,可以接收包含有空格的字符串
- String初始化为空字符串("\0"或 ""是等价的),也需要new字符数组,这样才能delete,如果用char *data="\0",不能用delete释放不是new出来的内存
- []需要重载两个版本,const版本 const char& operator[](size_t index) const; const成员函数的this指针隐式的转换为指向常量的指针: operator(const String *this, size_t index),const对象只能调用const menber function
- 不需要重载解引用*和取地址&,它们对自定义的类型也支持
- +=调用了operator+,问为什么operator+要返回引用,而不能返回对象?
- 没有实现重载的relational operators
- 相比标准库,自定义的String实现的接口很少,似乎什么都做不了,只能创建,赋值,输出,访问元素,甚至连标准库里的string开发中也不好用:为什么大多数的C++的开源库都喜欢自己实现一个string?
- new管理内存是否存在memory leak,是否有隐含的错误?
1 #include<iostream> 2 #include<string> 3 #include<vector> 4 #include<algorithm> 5 #include<cstdio> 6 #include<complex> 7 #include<new> 8 #include<memory> 9 #include<exception> 10 using namespace std; 11 // interfaces should supported 12 //用char*管理内存 13 class String 14 { 15 public: 16 String(); 17 String(const char*s); 18 String(size_t n, const char c);//用字符c填充String 19 String(const String&s); 20 String& operator=(const String&rhs); 21 String& operator=(const char*c); 22 char& operator[](size_t index);//要提供[]的两个版本 23 const char& operator[](size_t index)const; 24 String & operator*();//解引用重载是多余的,语言本身支持对所有类型的指针解引用,包括了自定义类型 25 String& operator+(const String&rhs); 26 String& operator+=(const String&rhs); 27 bool operator==(const String&rhs); 28 friend bool operator<(const String&lhs, const String&rhs); 29 friend ostream& operator<<(ostream& os, const String&rhs); 30 friend istream& operator>>(istream& in, String&rhs); 31 size_t size(); //如果是size_t length()会导致。。。。。 32 bool empty(); 33 const char* c_str(); 34 ~String(); 35 private: 36 char * data; 37 size_t length; 38 39 }; 40 String::String() //类外面定义menber function ,域作用符 41 { 42 this->data = new char[1](); //空字符串 ,strlen对data运算得到的长度为0 43 data[0] = '\0'; 44 (*this).length = 0; 45 } 46 String::String(const char*s) //允许implicit类型转换 47 { 48 // 不能用data=s;这导致创建的String对象与s共享了字符,而不是副本 49 length = strlen(s); 50 data = new char[length + 1]();//value initialization,申请了字符指针指向的内存区域 51 strcpy(data, s); 52 *(data + length) = '\0'; 53 } 54 String::String(size_t n, const char c) 55 { 56 length = n; 57 data = new char[length + 1](); 58 for (size_t i = 0; i < length;i++) 59 { 60 *(data + i) = c; 61 } 62 *(data + length) = '\0'; 63 } 64 String::String(const String&s) 65 { 66 length = s.length; 67 data = new char[length + 1](); //untill deconstructor to destory newed memory 68 for (size_t i = 0; i < length;i++) 69 { 70 data[i] = s.data[i]; 71 } 72 data[length] = '\0'; 73 } 74 String& String::operator=(const String&rhs) 75 { 76 if (this->data == rhs.data) return *this;// 支持*this==rhs的关系比较操作吗? 77 78 //assign 不是初始化,不需要申请内存空间,拷贝构造需要 ,但是原String与rhs大小可能不一样 79 delete[]data; //会导致重复删除data所指内存吗?? 80 81 length = rhs.length; 82 data = new char[length + 1](); 83 //如果发生异常 84 85 if (data == NULL) throw "allocate memory failed in copy ctr"; 86 for (size_t i = 0; i < length; i++) 87 { 88 data[i] = rhs.data[i]; 89 } 90 data[length] = '\0'; 91 } 92 char& String::operator[](size_t index) 93 { 94 if (index >= length||index<0) throw "out of range"; 95 return data[index];//如果data指向的字符串为"dhaj"这种不可修改的,会导致返回的引用不能有s[i]='c'的修改操作 96 } 97 String& String:: operator*() 98 { 99 if (this == NULL) throw "dereferrence null pointer "; 100 return *this; 101 } 102 String& String::operator+(const String&rhs)//a+b形式,也不改变a 103 { 104 String s;//不可伸缩,不能用来存a+b的结果 105 int len = strlen(this->data) + strlen(rhs.data); 106 char *p = new char[len + 1](); 107 for (size_t i = 0; i < strlen(this->data); i++) 108 { 109 p[i] = this->data[i]; 110 } 111 for (int j = strlen(this->data),i=0; j < len; j++,i++) 112 { 113 p[j] = rhs.data[i]; 114 } 115 p[len] = '\0'; 116 String *t = new String(p); //new了一个p,一个t,可以释放掉p,因为t是p的副本 117 delete[]p; 118 return *t;//返回了堆上的引用,再c=a+b这种使用后,c是会析构的,但中间这个看不见的对象不会析构 119 } 120 String& String::operator+=(const String&rhs) 121 { 122 *this = *this + rhs; 123 //释放掉原来的a,申请新空间 124 return *this; 125 } 126 bool String::operator==(const String&rhs)//比较是否相等,而不是相同 127 { 128 if (this->length != rhs.length) return false; 129 int i = 0; 130 for (; (*this).data[i] == rhs.data[i]; i++); 131 if (i != (rhs.length + 1)) return false; 132 else return true; 133 } 134 bool operator<(const String&lhs, const String&rhs) 135 { 136 return true; 137 } 138 ostream& operator<<(ostream& os, const String&rhs) //申明为友元函数。调用方式为cout<<s,申明为men fun,调用形式为s<<cout 139 { 140 os << rhs.data;//输出null pointer会未定义行为 141 return os; 142 } 143 istream& operator>>(istream& is, String&rhs) 144 {//输入一个字符串到字符指针,字符指针需要预先分配一定大小的空间,如何根据输入的字符串调整空间大小 145 delete[]rhs.data; 146 rhs.data = new char[50](); 147 is.getline(rhs.data, 50);//最后位置自动置为'\0',所以最多存49个字符,可接收空格 148 rhs.length = strlen(rhs.data); 149 return is; 150 } 151 size_t String::size() 152 { 153 return length; 154 } 155 bool String::empty() 156 { 157 if (length == 0) return true; 158 else return false; 159 } 160 const char* String::c_str()//返回指向对象局部部分的引用,指针,能用来修改原对象吗? 161 {//如果为空串,也要返回data 162 return data; 163 164 } 165 String::~String() 166 { // 析构会发生错误吗? 167 //String创建时会new内存,当程序结束或局部String对象退出作用域时调用析构函数,释放该内存 168 delete[]data; //如果String不是new出来的, 指针p指向它,delete p会导致错误,new出来的可以调用delete,这时会调用~String 169 data = NULL; 170 } 171 172 //int main() 173 //{ 174 // String s; 175 // cout << s << endl; 176 // cout << strlen(s.c_str()) << endl; 177 // String s1 = "whah"; 178 // cout << s1 << endl; 179 // String s2 = s1; 180 // cout <<"s2 length:"<< s2.size() << endl; 181 // s = s2; 182 // cout << "用s2赋值后的s: " << s << endl; 183 // String s3(10, 'c'); 184 // cout << "字符填充初始化s3: " << s3 << " " << "s3 len= " << s3.size() << endl; 185 // s3[0] = 'a'; 186 // cout << "下标修改s3后: " << s3 << endl; 187 // String s4 = s2 + s3+"ad"; //支持连续的+ 188 // cout << s4 << endl; 189 // String *sp = &s4; 190 // cout << *sp << endl; 191 // cout << strlen((*sp).c_str()) << endl; 192 // String *q = new String(*sp); 193 // cout << *q << endl; 194 // delete q; 195 // 196 // char *sq = const_cast<char*> (s4.c_str()); 197 // sq[0] = 'l'; 198 // cout << sq << endl; 199 // cout << s4 << endl; 200 // const char *cptr = s2.c_str(); 201 // string s5 = ""; 202 // string s6 = "\0"; 203 // cout << s5 << "**" << s6 << s5.size() << s6.size() << endl; 204 // string str = "jadj"; 205 // char *sptr = const_cast<char *> (str.c_str()); 206 // sptr[0] = 'd'; 207 // cout << sptr << " " << str << endl; 208 // String s7(s2); 209 // s7 += s4; 210 // cout << "s7: " << s7.size() << s7 << endl; 211 // const String s8("daj"); 212 // //s8[0]; 对const对象的[]调用,不能用non-const menber版本的operator[],要提供 const char& operator[]() const重载版本 213 // //s8 = "djwajk0"; 214 //} 215 216 int main() 217 { 218 string s2; 219 cin >> s2; 220 cout << s2 << endl; 221 String s, s1; 222 cin >> s >> s1;//用Enter间隔字符串,可接含有空格的字符串 223 cout << s <<"\n"<< s1 << endl; 224 cout << s1.size() << endl; 225 }
标签:
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有
上一篇:P3376 【模板】网络最大流
下一篇:路径搜索——网络寻路
- C++ 自动转换和强制类型转换(用户自定义类类型) 2020-06-10
- C++冒泡排序 (基于函数模板实现) 2020-05-31
- opencv-12-高斯滤波-双边滤波(附C++代码实现) 2020-05-10
- 二叉排序树 2020-05-02
- 抽象宠物类的实现 代码参考 2020-04-29
IDC资讯: 主机资讯 注册资讯 托管资讯 vps资讯 网站建设
网站运营: 建站经验 策划盈利 搜索优化 网站推广 免费资源
网络编程: Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术: Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧: 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷
网页制作: FrontPages Dreamweaver Javascript css photoshop fireworks Flash