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.dry(反义词)__________________  2.writ...
复活节英文怎么说 复活节英文怎么说?复活节的英语翻译是什么?复活节:Easter;"Easter,anniversar...
2008年北京奥运会主题曲 2008年北京奥运会(第29届夏季奥林匹克运动会),2008年8月8日到2008年8月24日在中华人...
英语道歉信 英语道歉信15篇  在日常生活中,道歉信的使用频率越来越高,通过道歉信,我们可以更好地解释事情发生的...
六年级英语专题训练(连词成句... 六年级英语专题训练(连词成句30题)  1. have,playhouse,many,I,toy,i...
上班迟到情况说明英语   每个人都或多或少的迟到过那么几次,因为各种原因,可能生病,可能因为交通堵车,可能是因为天气冷,有...
小学英语教学论文 小学英语教学论文范文  引导语:英语教育一直都是每个家长所器重的,那么有关小学英语教学论文要怎么写呢...
英语口语学习必看的方法技巧 英语口语学习必看的方法技巧如何才能说流利的英语? 说外语时,我们主要应做到四件事:理解、回答、提问、...
四级英语作文选:Birth ... 四级英语作文范文选:Birth controlSince the Chinese Governmen...
金融专业英语面试自我介绍 金融专业英语面试自我介绍3篇  金融专业的学生面试时,面试官要求用英语做自我介绍该怎么说。下面是小编...
我的李老师走了四年级英语日记... 我的李老师走了四年级英语日记带翻译  我上了五个学期的小学却换了六任老师,李老师是带我们班最长的语文...
小学三年级英语日记带翻译捡玉... 小学三年级英语日记带翻译捡玉米  今天,我和妈妈去外婆家,外婆家有刚剥的`玉米棒上带有玉米籽,好大的...
七年级英语优秀教学设计 七年级英语优秀教学设计  作为一位兢兢业业的人民教师,常常要写一份优秀的教学设计,教学设计是把教学原...
我的英语老师作文 我的英语老师作文(通用21篇)  在日常生活或是工作学习中,大家都有写作文的经历,对作文很是熟悉吧,...
英语老师教学经验总结 英语老师教学经验总结(通用19篇)  总结是指社会团体、企业单位和个人对某一阶段的学习、工作或其完成...
初一英语暑假作业答案 初一英语暑假作业答案  英语练习一(基础训练)第一题1.D2.H3.E4.F5.I6.A7.J8.C...
大学生的英语演讲稿 大学生的英语演讲稿范文(精选10篇)  使用正确的写作思路书写演讲稿会更加事半功倍。在现实社会中,越...
VOA美国之音英语学习网址 VOA美国之音英语学习推荐网址 美国之音网站已经成为语言学习最重要的资源站点,在互联网上还有若干网站...
商务英语期末试卷 Part I Term Translation (20%)Section A: Translate ...