C++string的模拟实现(上篇)
创始人
2024-05-22 12:58:39
0

目录

一.命名空间的封装与交换函数模板

1.命名空间的封装与类的定义

2.交换函数模板 

二.string类的四个重要默认成员函数

1.构造函数的类外定义:

2.析构函数在类外的定义

3.拷贝构造函数在类外的定义

4.赋值运算符重载在类外的定义 

5.关于两个string对象的内容交换问题

三.string类的迭代器 

四.string类的[]成员重载


一.命名空间的封装与交换函数模板

1.命名空间的封装与类的定义

模拟实现的string类最好用一个命名空间封装起来避免发生命名冲突。

命名空间定义:

namespace mystring
{//.....
}

类的定义(为了方便整理和维护,成员方法的声明和定义分离):

(本期不含增删查改的接口)


namespace mystring
{class string{public:typedef char * iterator;                  //宏定义string类的迭代器typedef const char* const_iterator;string(const char* nstr);                  //类中四个重要的默认成员函数string(const string& nstr);~string();string& operator=(string nstr);void copyswap(string &nstr);               //复用交换函数的接口iterator begin();                          //string类用于获取迭代器的接口iterator end();const_iterator begin()const;const_iterator end()const;const char * C_str()const;                 //用于返回C类型字符串的函数char & operator[](int pos);                //用于返回pos下标字符的引用的[]重载const char & operator[](int pos) const;     size_t size() const;                       //获取有效字符个数size和容量的接口size_t capacity() const;private:char * _str;size_t _size;size_t _capacity;};}

2.交换函数模板 

template 
void myswap (T& e1 , T&e2)
{T tem = e1;e1 = e2;e2 =tem;
}

该模板可以根据传入的实参类型生成用于交换对应类型数据的函数实例。

二.string类的四个重要默认成员函数

1.构造函数的类外定义:

类外声明方法时注意表明方法所在命名空间和类域

mystring::string::string(const char* nstr = "") :_size(strlen(nstr))                            ,_capacity (_size)
{                          _str = new char[_capacity+1];                strcpy(_str,nstr);
}
  • 设计缺省参数是为了保证类的构造函数可以被无参调用,(形参缺省值可用于构造空字符串)(会完成'\0'的拷贝)(注意参数缺省值只能写在函数的声明和定义其中一个之中)
  • strlen函数中有关于空指针的断言,所以构造函数中无须进行空指针断言
  •  +1是为了保存'\0'(不计入容量和有效字符),同时保证_str不为空指针(对象只要创建出来就一定要维护一块堆空间,防止析构的时候程序崩溃)

2.析构函数在类外的定义

mystring::string::~string()
{if(_str){delete[] _str;      释放堆区空间_str=nullptr;}_size=0;_capacity=0;
}

3.拷贝构造函数在类外的定义

    mystring::string::string(const string& nstr):_size(nstr._size),_capacity(nstr._capacity){_str = new char[_capacity+1];             strcpy(_str,nstr._str);}

这是一种非复用的写法,现代STL中比较喜欢使用复用的写法,拷贝构造函数可以通过复用构造函数来实现,从而使代码更加简洁:

现在类中定义一个成员交换函数(该函数通过复用swap函数实现):

    //template //void myswap (T& e1 , T&e2)//{//   T tem = e1;//   e1 = e2;//   e2 =tem;//}void mystring::string::copyswap(string & nstr){myswap(_str,nstr._str);myswap(_size,nstr._size);myswap(_capacity,nstr._capacity);}

调用该成员函数可以将两个string对象的各个成员变量进行交换

复用构造函数实现拷贝构造函数:

    mystring::string::string(const string& nstr)     //复用构造函数完成拷贝构造:_str (nullptr)                                  //防止tem中_str作为野指针被释放,_size(0),_capacity(0){string tem(nstr._str);                       //拷贝构造拷贝的是不含'\0'的有效字符this->copyswap(tem);                         //为了方便阅读加上this指针}

该实现方法的思想是通过形参对象中的字符串构造tem临时对象,再将tem对象中的内容通过交换函数置换到被构造的对象中去。

tem在函数体执行完后会自动调用自身的析构函数并销毁。

4.赋值运算符重载在类外的定义 

   string& mystring::string::operator=(const string& nstr){if(this != &nstr)                           //判断重载操作数是否为同一个对象{char * tem = new char[nstr._capacity+1];  strcpy(tem,nstr._str);delete[] _str;                           //释放原来的堆区空间_str = tem;_size = nstr._size;_capacity = nstr._capacity;}return *this;}
  • 注意不能直接用_str去接收新申请的堆区空间地址(因为new可能会失败)
  • 注意返回对象本身的引用*this(使=重载可以满足连等赋值)

赋值运算符重载也可以通过复用拷贝构造来实现:

    string& mystring::string::operator=(string nstr)     {copyswap(nstr);return (*this);}
  • 复用拷贝构造实现赋值运算符重载的思路:

5.关于两个string对象的内容交换问题

  • STL的标准库中string类中有成员交换函数swap(相当于本篇模拟实现中的copyswap成员函数),使用成员函数完成两个string对象的内容交换效率远高于直接使用全局swap函数(相当于本篇模拟实现中的myswap函数)完成两个string对象的内容交换
  • 直接调用全局交换函数交换两个string对象会额外调用对象的拷贝构造函数和赋值运算符重载从而增加性能消耗(new申请空间的性能消耗是很大的)

比如:

using mystring::string;
using mystring::myswap;int main()
{string a("hello");string b("world");myswap(a,b);    交换方式一(直接调用全局交换函数)a.copyswap(b);  交换方式二(调用成员交换函数)return 0;}

两种对象交换的方式差异图解:

三.string类的迭代器 

string类的迭代器可以typedef为字符指针

    mystring::string::iterator mystring::string:: begin(){return _str;}mystring::string::iterator mystring::string::end(){return _str+_size; }mystring::string::const_iterator mystring::string::begin()const{return _str;}mystring::string::const_iterator mystring::string::end()const{return _str+_size;}

四.string类的[]成员重载

string类的[]成员重载用于返回字符串中指定下标的字符的引用

    char &  mystring::string::operator[](int pos){assert(pos<_size);return _str[pos];}const char &  mystring::string::operator[](int pos) const{assert(pos<_size);return _str[pos];}
  • const修饰的重载成员是供const修饰的string对象调用的

完整代码:

#include
#include
#include 
//只要不涉及寻址,一定要注意编译器的顺序编译机制namespace mystring
{class string{public:typedef char * iterator; typedef const char* const_iterator;string(const char* nstr);                  //类中四个重要的默认成员函数string(const string& nstr);~string();string& operator=(string nstr);void copyswap(string &nstr);               //复用交换函数的接口iterator begin();                          //string类用于获取迭代器的接口iterator end();const_iterator begin()const;const_iterator end()const;const char * C_str()const;                 //用于返回C类型字符串的函数char & operator[](int pos);                //用于返回pos下标字符的引用的[]重载const char & operator[](int pos) const;     size_t size() const;                       //获取有效字符个数size和容量的接口size_t capacity() const;private:char * _str;size_t _size;size_t _capacity;};template void myswap (T& e1 , T&e2){T tem = e1;e1 = e2;e2 =tem;}void mystring::string::copyswap(string & nstr){myswap(_str,nstr._str);myswap(_size,nstr._size);myswap(_capacity,nstr._capacity);}const char * mystring::string::C_str() const{return _str;}mystring::string::string(const char* nstr = "")  //缺省值用于构造空字符串(会完成'\0'的拷贝)(注意缺省参数只能写在声明和定义其中一个之中):_size(strlen(nstr))                             //strlen函数中有关于空指针的断言,所以构造函数中无须进行空指针判断,_capacity (_size){                          _str = new char[_capacity+1];                // +1是为了保存'\0'(不计入容量和有效字符),同时保证_str不为空指针(对象只要创建出来就一定维护一块堆空间)strcpy(_str,nstr);}// mystring::string::string(const string& nstr)  //非复用式写法// :_size(nstr._size)// ,_capacity(nstr._capacity)// {//     _str = new char[_capacity+1];             // +1是为了保存'\0'(不计入容量和有效字符),同时保证_str不为空指针//     strcpy(_str,nstr._str);// }mystring::string::string(const string& nstr)     //复用构造函数完成拷贝构造:_str (nullptr)                                  //防止tem中_str作为野指针被释放,_size(0),_capacity(0){string tem(nstr._str);                       //拷贝的是不含'\0'的有效字符this->copyswap(tem);                         //为了方便阅读加上this指针}// string& mystring::string::operator=(const string& nstr)// {//     if(this != &nstr)                             //判断重载操作数是否为同一个对象//     {//         char * tem = new char[nstr._capacity+1];  // +1是为了保存'\0'(不计入容量和有效字符)//         strcpy(tem,nstr._str);//         delete[] _str;//         _str = tem;//         _size = nstr._size;//         _capacity = nstr._capacity;//     }//     return *this;// }string& mystring::string::operator=(string nstr)     //与直接交换对象作对比{copyswap(nstr);return (*this);}mystring::string::~string(){if(_str){delete[] _str;_str=nullptr;}_size=0;_capacity=0;}mystring::string::iterator mystring::string:: begin(){return _str;}mystring::string::iterator mystring::string::end(){return _str+_size; }mystring::string::const_iterator mystring::string::begin()const{return _str;}mystring::string::const_iterator mystring::string::end()const{return _str+_size;}char &  mystring::string::operator[](int pos){assert(pos<_size);return _str[pos];}const char &  mystring::string::operator[](int pos) const{assert(pos<_size);return _str[pos];}size_t mystring::string::size() const{return _size;}size_t mystring::string::capacity() const{return _size;}

相关内容

热门资讯

惊鸿舞主持词 惊鸿舞主持词汇总  1、《Lightspeed》  男:青春,是阳光下初融的冰雪,叮咚叮咚奏响着奇幻...
主持人串词等 主持人串词等五篇  第一篇:《新款文艺汇演主持人串词》  2014年文艺汇演主持人串词  男1、女1...
初中毕业典礼主持词开场白 初中毕业典礼主持词开场白  时光弹指一挥间悄然而逝,在这个栀子花开的季节,初中学生即将毕业,初中毕业...
运动会主持词 运动会主持词范本合集5篇  根据活动对象的不同,需要设置不同的主持词。随着中国在不断地进步,越来越多...
晚会节目主持串词 晚会节目主持串词  篇一:第五届艺体节节目主持串词  第五届艺体节节目主持串词 下午衔接:各位老师,...
《为了谁》节目主持词 《为了谁》节目主持词  持人在台上所表演的主持词,则是集会的灵魂之所在。下面是小编收集整理的《为了谁...
新郎婚礼致辞 关于新郎婚礼致辞(精选5篇)  在日常学习、工作和生活中,大家都写过致辞吧,致辞是指在举行会议或某种...
乔迁的感谢词 乔迁的感谢词  尊敬的各位来宾、女士们、先生们、亲爱的父老乡亲们:  大家好!  首先我代表我的家人...
开业致辞 开业致辞(通用6篇)  在日复一日的学习、工作或生活中,大家或多或少都用到过致辞吧,致辞要求风格的雅...
80岁生日庆典主持词 80岁生日庆典主持词(精选5篇)  主持词可以采用和历史文化有关的表述方法去写作以提升活动的文化内涵...
感恩节活动主持词 2022年感恩节活动主持词  根据活动对象的不同,需要设置不同的主持词。在如今这个中国,我们对主持词...
电视剧《一起同过窗》经典的台... 电视剧《一起同过窗》经典的台词  在社会一步步向前发展的今天,很多情况下我们需要用到台词,台词是用以...
开门红主持词 开门红主持词  活动对象的不同,主持词的写作风格也会大不一样。在现在的社会生活中,主持人在活动中起到...
六一儿童节慰问活动致辞 六一儿童节慰问活动致辞(通用5篇)  在我们平凡的日常里,大家一定都接触过致辞吧,致辞具有有张有弛、...
生日主持词 关于生日主持词范文集锦五篇  主持词要注意活动对象,针对活动对象写相应的主持词。在当今社会生活中,司...
春晚节目主持人 临近春节,中央电视台毫无悬念地对外宣布70后吕逸涛,正式出任2016年猴年央视春晚总导演。消息公布后...
教师节领导简短致辞 教师节领导简短致辞(精选8篇)  在日常学习、工作和生活中,大家都不可避免地要接触到致辞吧,致辞讲求...
同学会主持词 【精华】同学会主持词(通用10篇)  主持词要根据活动对象的不同去设置不同的主持词。在当今社会生活中...
演讲比赛闭幕词 演讲比赛闭幕词范文(精选8篇)  要增加主持词的文化内涵,达到寓教于乐的主持词的写作,在不增加篇幅的...
学子宴主持词 学子宴主持词  各位女士、各位嘉宾、各位亲朋挚友,  合:大家好!  女:今日,初秋丽日,艳阳高照;...