C++中sting类的简单实现方法
String
在C++的学习生涯我中发现String类的功能十分强大,所以我们是很有必要模拟实现它的,况且在面试的时候模拟实现一个String类也是面试官经常会考的,但是因为外界因素的限制我们是不可能模拟的和库里的string一致的(C++库里的string功能更强大),所以今天我们只模拟实现string的基本功能-构造函数,拷贝构造函数,析构函数,赋值运算符重载,运算符+=的重载,运算符[]的重载,c_str(得到一个C风格的字符指针,可操作字符串),Size,Push_Back,Insert(深拷贝),以及用写时拷贝copy_on_write的方式实现基本的String类
深拷贝的方式
class String { friend ostream &operator<<(ostream &os,String &s); public: String(const char *str=""); //全缺省的构造函数,解决空字符串的问题 String(const String &ps); //深拷贝 String &operator=(String s); String &operator+=(const char * s); const char *C_Str()const //得到C风格的字符指针 { return _pstr; } char &operator[](size_t index) { return _pstr[index]; } size_t Size()const { return _size; } void PushBack(char c); String &Insert(size_t pos,const char *str); //String &operator=(String &s) //{ // cout<<"String &operator=(String &s)"<<endl; // if(this != &s) // { // delete[]_pstr; // _pstr=new char[strlen(s._pstr)+1]; // strcpy(_pstr,s._pstr); // } // return *this; //} ~String() { cout<<"~String()"<<endl; if(_pstr != NULL) { delete[]_pstr; _pstr=NULL; _size=0; _capacity=0; } } private: void CheckCapacity(int count); private: int _size; int _capacity; char *_pstr; }; ostream &operator<<(ostream &os,String &s) { os<<s._pstr; return os; } String::String(const char *str) :_size(strlen(str)) ,_capacity(strlen(str)+1) ,_pstr(new char[_capacity]) { cout<<"String()"<<endl; strcpy(_pstr,str); } String::String(const String &ps) :_size(ps._size) ,_capacity(strlen(ps._pstr)+1) ,_pstr(new char[_capacity]) { cout<<"String(const String &ps)"<<endl; strcpy(_pstr,ps._pstr); } String &String::operator=(String s) { cout<<"String &operator=(String s)"<<endl; std::swap(_pstr,s._pstr); std::swap(_size,s._size); std::swap(_capacity,s._capacity); return *this; } void String::CheckCapacity(int count) { if(_size+count >= _capacity) { int _count=(2*_capacity)>(_capacity+count)?(2*_capacity):(_capacity+count); char *tmp=new char[_count]; strcpy(tmp,_pstr); delete[]_pstr; _pstr=tmp; _capacity=_count; } } void String::PushBack(char c) { CheckCapacity(1); _pstr[_size++]=c; _pstr[_size]='\0'; } String &String::operator+=(const char * s) { CheckCapacity(strlen(s)); while(*s) { _pstr[_size++]=*s; s++; } _pstr[_size]='\0'; return *this; } String &String::Insert(size_t pos,const char *str) { char *tmp=new char[strlen(_pstr+pos)]; strcpy(tmp,_pstr+pos); CheckCapacity(strlen(str)); while(*str) { _pstr[pos++]=*str; str++; } strcpy(_pstr+pos,tmp); return *this; }
通过测试上述代码可正常运行,特别是在实现赋值运算符重载的时候我们使用了两种方式,值得一提的是应用swap函数来实现赋值运算符的重载(在传参时不可以传引用),因为应用swap函数实现是根据临时变量的创建并且该临时变量出作用域就会自动调用析构函数销毁(现代的方法)
测试深拷贝的方法
void text1() { String str1("hello"); String str2(str1); String str3; str3=str1; cout<<str1<<endl; cout<<str2<<endl; cout<<str3<<endl; cout<<strlen(str1.C_Str())<<endl; //5 str1[4]='w'; cout<<str1<<endl; //hellw } void text2() { String str1("abcd"); cout<<str1<<endl; str1.PushBack('e'); str1.PushBack('f'); str1.PushBack('g'); str1.PushBack('h'); str1.PushBack('i'); cout<<str1<<endl; cout<<str1.Size()<<endl; } void text3() { String str1("hello"); String str2("hello world"); String str3(str2); str1+=" "; str1+="world"; cout<<str1<<endl; str2.Insert(6," abc "); cout<<str2<<endl; }
实现了深拷贝的方法那仫有没有更加高效的方法呢?当然,那就是写时拷贝,我们发现在上述深拷贝的版本里实现的拷贝构造函数又为新的对象重新开辟空间(防止浅拷贝的后遗症:浅拷贝是值拷贝使得两个指针指向同一块空间,在析构该空间时对同一块空间释放多次就会出现问题),那仫如果我们继承了浅拷贝的后遗症-就让多个指针指向同一块空间,此时我们只需要设置一个指针变量让它记录指向这块空间的指针个数,在析构时只要该指针变量的内容为1我们就释放这块空间否则就让计数器减1,这就是写时拷贝的主要思想,下面就让我们用写时拷贝的方法实现一个简单的String类吧
写时拷贝的方法
//写时拷贝的方式 class String { friend ostream& operator<<(ostream & os,String &s); public: String(const char *str="") :_str(new char[strlen(str)+1+4]) { cout<<"构造"<<endl; _str+=4; *((int *)(_str-4))=1; strcpy(_str,str); } String(String &s) { cout<<"拷贝构造"<<endl; ++*((int *)(s._str-4)); _str=s._str; } String &operator=(const String &s) { cout<<"赋值语句"<<endl; if(--*(int *)(_str-4) == 0) { delete[](_str-4); } ++(*(int *)(s._str-4)); _str=s._str; return *this; } char &operator[](int index) //写时拷贝 { assert(index >= 0 && index < (int)strlen(_str)); if(*(int *)(_str-4) > 1) { --*(int *)(_str-4); char *tmp=new char[strlen(_str)+5]; strcpy(tmp+4,_str); delete[](_str-4); _str=tmp+4; *(int *)(_str-4)=1; } return _str[index]; } ~String() { cout<<"析构"<<endl; if(--*(int *)(_str-4) == 0) { cout<<"释放"<<endl; delete[](_str-4); } } private: char *_str; }; ostream& operator<<(ostream &os,String &s) { os<<s._str; return os; }
在这里我们将指针指向的计数器的位置放置在数据空间的前四个字节处
测试用例:
void test1() { String str1("abcd"); cout<<str1<<endl; String str2(str1); cout<<str2<<endl; String str3; str3=str1; cout<<str3<<endl; } void test2() { String str1("abcd"); cout<<str1<<endl; String str2; str2=str1; cout<<str2<<endl; str2[2]='w'; cout<<str2<<endl; }
以上所述是小编给大家介绍的C++中sting类的简单实现方法,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对我们网站的支持!
栏 目:C语言
下一篇:C语言 数组指针详解及示例代码
本文标题:C++中sting类的简单实现方法
本文地址:https://www.xiuzhanwang.com/a1/Cyuyan/2092.html
您可能感兴趣的文章
- 04-02func函数+在C语言 func函数在c语言中
- 04-02c语言中对数函数的表达式 c语言中对数怎么表达
- 04-02c语言没有round函数 round c语言
- 04-02C语言中怎么打出三角函数 c语言中怎么打出三角函数的值
- 01-10深入理解C++中常见的关键字含义
- 01-10使用C++实现全排列算法的方法详解
- 01-10深入Main函数中的参数argc,argv的使用详解
- 01-10APUE笔记之:进程环境详解
- 01-10c++中inline的用法分析
- 01-10如何寻找数组中的第二大数
阅读排行
本栏相关
- 04-02c语言函数调用后清空内存 c语言调用
- 04-02func函数+在C语言 func函数在c语言中
- 04-02c语言的正则匹配函数 c语言正则表达
- 04-02c语言用函数写分段 用c语言表示分段
- 04-02c语言中对数函数的表达式 c语言中对
- 04-02c语言编写函数冒泡排序 c语言冒泡排
- 04-02c语言没有round函数 round c语言
- 04-02c语言分段函数怎么求 用c语言求分段
- 04-02C语言中怎么打出三角函数 c语言中怎
- 04-02c语言调用函数求fibo C语言调用函数求
随机阅读
- 01-11ajax实现页面的局部加载
- 08-05dedecms(织梦)副栏目数量限制代码修改
- 01-11Mac OSX 打开原生自带读写NTFS功能(图文
- 01-10delphi制作wav文件的方法
- 01-10SublimeText编译C开发环境设置
- 08-05DEDE织梦data目录下的sessions文件夹有什
- 01-10C#中split用法实例总结
- 04-02jquery与jsp,用jquery
- 01-10使用C语言求解扑克牌的顺子及n个骰子
- 08-05织梦dedecms什么时候用栏目交叉功能?