learn C++ NO.11——string类模拟实现

这篇具有很好参考价值的文章主要介绍了learn C++ NO.11——string类模拟实现。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言

本篇文章主要是讲string类的模拟实现,模拟实现的是string类的常用接口以及成员函数。让读者对string类有更深的理解。适当的“造轮子”,有助于我们的语言学习。

简单描述string类

string类其实就是一个管理字符数组的线性表,我们可以使用string头文件内提供的接口来对string类进行数据的增删查改。

第一部分:初步搭建一个string类最基本的框架

learn C++ NO.11——string类模拟实现,C++学习,c++,开发语言
我们以上面图中的一个简单的程序为模拟实现的第一个部分。首先,我们需要定义一个string类。然后,定义string类的成员变量。提供构造函数和析构函数。最后,提供一个c_str接口能够是<<运算符能够提取出模拟实现的string类的数据。

定义成员变量

我们将要实现的string类实现的成员变量如下,定义一个char类型指针的成员变量_str,来保存在堆上动态开辟的内存空间。分别定义两个无符号整型成员变量_size和_capacity,顾名思义_size用于记录string类对象的有效数据个数,_capacity用于记录string类对象的在堆上开辟空间的大小。需要将成员变量私有,以防止在类域外面能够访问修改数据。仅提供对应接口让用户能够访问成员变量的内容。
learn C++ NO.11——string类模拟实现,C++学习,c++,开发语言

构造函数的模拟实现

这里我们实现的是通过一个c字符串的内容来构造一个string类的全缺省构造函数。它同样可以完成string类的默认构造的对应功能。
实现思路: 首先,我们先通过strlen()求出需要形参部分的字符串的长度,并将结果保存到一个临时变量中。然后,new一块长度为形参部分长度的空间+1赋值给_str(这里+1是为了放’\0’)。将形参部分的字符串的长度赋值给_size和_capacity。最后,在函数体内直接通过c库函数strcpy来将形参的内容拷贝给_str。
learn C++ NO.11——string类模拟实现,C++学习,c++,开发语言
这里我们在默认参数中给的是一个空串,其实这里是一个很妙的处理。c语言中规定""引起的字符串内容中包含一个隐藏的’\0’。当我们不传参数时,我们还是会开辟一个字节的空间存放’\0’字符来初始化string类对象。

析构函数的模拟实现

因为string类的数据需要存放在堆区上,所以析构函数需要我们实现,编译器默认生成的析构函数无法完成对堆区资源的释放。只需要将堆区空间释放并处理_size和_capacity即可。
learn C++ NO.11——string类模拟实现,C++学习,c++,开发语言

c_str()函数的模拟实现

learn C++ NO.11——string类模拟实现,C++学习,c++,开发语言
c_str()函数是获取string类的内筒,以c字符串形式返回。简而言之,c_str()接口返回的是成员变量_str。需要注意的是需要使用const来修饰一下返回值,以保护成员变量_str。
learn C++ NO.11——string类模拟实现,C++学习,c++,开发语言

至此第一部分的最最基本的string类的框架就搭建好了,下面我们再稍微完善完善模拟实现的string类。

第二部分:进一步完善功能

size()函数的模拟实现和capacity()的模拟实现

size()函数用于获取string类有效元素的个数,本质其实就是返回_size的值。capacity()函数用于获取string类在堆区开辟的空间的长度,返回的是成员变量_capacity。

learn C++ NO.11——string类模拟实现,C++学习,c++,开发语言

[]运算符重载的模拟实现

由于库里string类是重载了操作符[],使得string类像数组一样。这极大程度上方便用户对于string类的某一个位置的数据进行增删查改。
实现思路: 实现思路就是返回_str的某一个位置的字符。需要注意的是库里面对于下标有效性的检查是assert的暴力检查。
learn C++ NO.11——string类模拟实现,C++学习,c++,开发语言

迭代器及相关成员函数模拟实现

string类的迭代器其实就是一个类似于指针的一个东西,本质是其成员函数_str,但是迭代器不一定都是指针。例如list,其迭代器就不是指针,具体细节等模拟实现list时再说。begin()其实就是返回string类对象第一个元素的地址,end()返回的是string类对象有效字符的下一个地址('\0’的地址)。

learn C++ NO.11——string类模拟实现,C++学习,c++,开发语言

learn C++ NO.11——string类模拟实现,C++学习,c++,开发语言
有了迭代器就可以支持范围for语法。因为范围for的底层是通过迭代器来实现的。这里就简单做个演示。
learn C++ NO.11——string类模拟实现,C++学习,c++,开发语言

reserve()函数的模拟实现

reserve函数用于将_str在堆区申请的空间大小进行调整。
实现思路:当调整的值 > _capacity时就进行扩容,当n<_capacity不做处理。开辟一段长度为n的堆区空间,将_str的值拷贝给新开辟的空间(需要拷贝’\0’),随后释放_str。最后将tmp赋值给_str,将_capacity修改成n。
learn C++ NO.11——string类模拟实现,C++学习,c++,开发语言

resize(size_t n, char ch = ‘\0’)函数的模拟实现

resize()函数用于调整string类对象有效字符的长度至指定的长度,也支持指定字符来进行初始化。
learn C++ NO.11——string类模拟实现,C++学习,c++,开发语言
实现思路:当n小于当前string对象有效长度时,将n赋值给_size,有效长度的后一个位置添上’\0’。当n大于string对象有效长度时,先用reserve来调整有效的空间大小,然后从_size后开始写入字符ch直到有效长度达到n。修改_size的值为n。
learn C++ NO.11——string类模拟实现,C++学习,c++,开发语言

push_back()函数 的模拟实现

push_back()函数就是在string类对象的有效长度的下一位插入元素。这里以插入一个字符的版本为例进行模拟实现。
实现思路:先判断空间是否足够,若不够就扩容。然后在第_size个位置插入字符。随后++_size,并在_size下标位置上放上’\0’。
learn C++ NO.11——string类模拟实现,C++学习,c++,开发语言

append()函数的模拟实现

append()函数就是在string类对象的有效长度后追加数据,这里以常用的追加一个c字符串为例模拟实现。
实现思路:首先,判断堆区空间是否足够。然后,在_size下标出,将c字符串拷贝c字符串长度个数据到_size后的空间。最后更新string类对象的有效长度。
learn C++ NO.11——string类模拟实现,C++学习,c++,开发语言

operator += 重载的模拟实现

由于上面我们已经实现了push_back()和append()接口,这里我们至今进行一波复用就可以啦。
learn C++ NO.11——string类模拟实现,C++学习,c++,开发语言

insert()函数的模拟实现

这里我们分别模拟实现两个版本,一个是在pos位置插入n个字符,另一个是在pos位置插入一个c字符串。再此之前我要引入一个新的成员变量npos,他是一个静态的公用成员变量,它表示的是最大的无符号整型值,即-1(2^32-1)。

实现思路:首先,判断一下pos下标的合法性。然后,判断堆区空间是否足够,不够就扩容。接下来,从pos位置开始向后挪动数据(需要注意边界控制),挪动n位。在pos位置插入n个字符或者一个c字符串。最后,更新一下_size。
learn C++ NO.11——string类模拟实现,C++学习,c++,开发语言

find()函数的模拟实现

find接口用于从pos下标处开始查找一个字符或者一个字符串在当前string类对象的下标,没有找到则返回npos,所以我们还是实现两个版本。
实现思路:先判断下标的合法性。字符串版本进行strstr匹配,成功找到的话返回strstr的返回值-_str的偏移量,没有找到则返回npos。字符版本,直接使用一个for循环遍历string类对象,找到了就返回对应下标,否则返回npos。
learn C++ NO.11——string类模拟实现,C++学习,c++,开发语言

erase()函数的模拟实现

erase函数用于删除从pos下标处开始,删除长度为len个数据。
实现思路:首先,判断pos下标的合法性。然后,根据len来判断删除的方式,若len = npos或者pos + len > _size,即从pos位置开始直接删完。若pos + len < _size,则需要挪动数据覆盖。
learn C++ NO.11——string类模拟实现,C++学习,c++,开发语言

两个string类比较运算符重载的实现

这里就重点讲 重载< 和 重载== 的实现。只要实现这两个运算符,其余的比较运算符只需要复用它们俩就行。
实现思路:先讲 < 重载的实现。我们先找到两个string类有效长度短的那一个作memcmp的num参数。然后,根据memcmp的返回值进行判断。若返回值等于0,只需要判断_size是否小于s._size。若小于返回真,否则返回假。其他情况下,ret只要小于0,就返回真,否则返回假。而 == 重载需要我们先比较两个string类对象的有效长度是否一样,不一样直接返回假。一样的情况下,再进行memcmp,返回值为0才为真,否则为假。

learn C++ NO.11——string类模拟实现,C++学习,c++,开发语言
其余情况复用上面两个运算符重载函数即可。
learn C++ NO.11——string类模拟实现,C++学习,c++,开发语言

流插入运算符重载的模拟实现

实现思路:通过循环将string类对象的内容一个字符一个字符的流入到ostream类对象中,最后返回这个类对象。
learn C++ NO.11——string类模拟实现,C++学习,c++,开发语言

流提取运算符重载的模拟实现

实现思路:第一步,需要清空string类的数据。紧接着,将缓冲区的空格和换行给清掉。我们定义一个buffer数组来存放从键盘上输入的字符,这样可以减少扩容所带来的性能消耗。然后将buffer追加到string类对象中即可。需要注意的是由于io流里面默认是以空格和换行进行分割的。所有在模拟实现流提取运算符重载时,我们需要用到一个接口就是get()。

learn C++ NO.11——string类模拟实现,C++学习,c++,开发语言

深浅拷贝

浅拷贝的介绍

首先,下面请看一段代码
learn C++ NO.11——string类模拟实现,C++学习,c++,开发语言
这里由于我们没有实现拷贝构造,编译器默认生成的拷贝构造导致了同一块内存被析构函数释放了两次。为什么呢?因为编译器默认生成的拷贝构造是浅拷贝,即值拷贝。其实就是将s1的三个成员变量的内容直接赋值给s2。main函数生命周期即将结束时,调用析构函数清理动态申请内存时,同一块动态申请的内存被释放了两次,导致的程序错误。此时,就需要使用深拷贝进行解决此问题。

深拷贝的介绍

深拷贝是指在拷贝对象时,不仅拷贝对象的值,还要拷贝对象所指向的内存空间,即重新分配一块内存空间,并将原对象的值复制到新的内存空间中。这样,原对象和拷贝对象就互不干扰,修改一个对象的值不会影响另一个对象的值。深拷贝通常需要自定义拷贝构造函数和赋值运算符重载函数来实现。

learn C++ NO.11——string类模拟实现,C++学习,c++,开发语言

拷贝构造的模拟实现

这里我依次介绍传统写法以及现代写法的拷贝构造。
传统写法实现思路:先开辟根据被拷贝对象的大小申请空间并给_str,随后将被拷贝对象的数据内容拷贝到_str中,最后将被拷贝对象的_size和_capacity的值赋值给拷贝对象的_size和_capacity中。
learn C++ NO.11——string类模拟实现,C++学习,c++,开发语言
现代写法实现思路: 先定义一个局部string对象tmp并用被拷贝的string类对象的内容去构造他,然后调用swap函数来将tmp对象的内容交换给拷贝对象。随后除了作用域tmp对象会被析构。就完成了拷贝构造的现代写法。这就像你假期在家时,让你的弟弟妹妹给你当工具人,吃饭让他们给你端进房间,吃完了他们还给你把碗筷收拾干净了端走。这里的tmp临时对象起到的就是这个作用。
learn C++ NO.11——string类模拟实现,C++学习,c++,开发语言

operator = 重载的模拟实现

其实有了上面现代写法为基础,operator = 的实现思路大致也是一致,利用swap将形参的临时对象tmp内容交换给我们的拷贝对象即可。
learn C++ NO.11——string类模拟实现,C++学习,c++,开发语言

substr()函数的模拟实现

有了对深浅拷贝的初步理解,接下来就带大家模拟实现一个常用的string类的接口substr()。substr()其实就是在当前string类对象的pos下标处构造一个长度为len的子串。
实现思路:首先,需要判断pos位置的有效性。然后,定义一个临时对象tmp。判断一下需要构造的子串的长度并修正。提前给tmp开辟好合适的容量,直接拷贝数据给tmp。最后,返回临时对象tmp。
learn C++ NO.11——string类模拟实现,C++学习,c++,开发语言

总结

对string类的模拟实现主要是为了能够让我们更进一步的掌握string类。会使用string类和掌握string类底层逻辑,两者还是有很大的区别的。知其然,知其所以然。在学习语言时,适当的”造轮子“可以让你的水平更进一步。点击获取完整代码文章来源地址https://www.toymoban.com/news/detail-722407.html

到了这里,关于learn C++ NO.11——string类模拟实现的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【C++初阶】学习string类的模拟实现

    前面已经学习了string类的用法,这篇文章将更深入的学习string类,了解string类的底层是怎么实现的。当然,这里只是模拟一些常用的,不常用的可以看文档学习。 我们一共创建两个文件,一个是test.cpp文件,用于测试;另一个是string.h文件,用于声明和定义要模拟的string类。

    2024年02月03日
    浏览(40)
  • Learning C++ No.28 【C++11语法实战】

    北京时间:2023/6/5/9:25,今天8点45分起床,一种怎么都睡不够的感觉,特别是周末,但是如果按照我以前的睡觉时间来看,妥妥的是多睡了好久好久,并且昨天也睡了一天,哈哈哈,睡觉这方面,真的睡能比我强,昨天是实训课,课程内容主要就是做一些C语言二级的题目,虽

    2024年02月08日
    浏览(27)
  • 【C++心愿便利店】No.11---C++之string语法指南

    👧个人主页:@小沈YO. 😚小编介绍:欢迎来到我的乱七八糟小星球🌝 📋专栏:C++ 心愿便利店 🔑本章内容:string 记得 评论📝 +点赞👍 +收藏😽 +关注💞哦~ 提示:以下是本篇文章正文内容,下面案例可供参考 C语言中,字符串是以’\\0’结尾的一些字符的集合,为了操作方

    2024年02月05日
    浏览(36)
  • Learning C++ No.26 【深入学习位图】

    北京时间:2023/5/30/15:30,刚睡醒,两点的闹钟,硬是睡到了2点40,那种睡不醒的感觉,真的很难受,但是没办法,欠的课越来越多,压的我喘不过气了都,早上把有关unordered_set和unordered_map的内容给写完了,所以哈希表有关代码方面的知识,我们就搞定的差不多了,并且现在

    2024年02月07日
    浏览(28)
  • 【C++】手撕string(string的模拟实现)

    手撕string目录: 一、 Member functions 1.1 constructor 1.2  Copy constructor(代码重构:传统写法和现代写法) 1.3 operator=(代码重构:现代写法超级牛逼) 1.4 destructor 二、Other member functions 2.1 Iterators(在string类中,迭代器基本上就是指针) 2.1.1 begin() end() 2.1.2  范围for的底层

    2024年02月08日
    浏览(36)
  • 【C++】模拟实现string

      目录 🌞专栏导读 🌛定义string类  🌛构造函数 🌛拷贝构造函数 🌛赋值函数 🌛析构函数  🌛[]操作符重载  🌛c_str、size、capacity函数  🌛比较运算符重载   🌛resize与reserve函数 🌛push_back、append函数  🌛insert函数  🌛erase函数 🌛find函数  🌛swap函数 🌛clean函数  🌛

    2024年02月14日
    浏览(35)
  • C++——string模拟实现

    前言:上篇文章我们对string类及其常用的接口方法的使用进行了分享,这篇文章将着重进行对这些常用的接口方法的内部细节进行分享和模拟实现。 目录 一.基础框架 二.遍历字符串 1.[]运算符重载 2.迭代器 3.范围for 三.常用方法 1.增加 2.删除 3.调整 4.交换 5.查找 6.截取 7.比较

    2024年03月12日
    浏览(29)
  • 【C++】string模拟实现

    个人主页🍖:在肯德基吃麻辣烫 本文带你进入string的模拟实现,对于string,是我们深入学习STL的必要途径。 我在模拟实现string时,成员变量如下: 1.1 无参构造(默认构造) 构造时不进行任何初始化,则默认为空字符串 比如: bit::sring s1; 1.2 普通构造 思路: 1.先新申请一块空

    2024年02月16日
    浏览(37)
  • 【C++】string类模拟实现

    🚀 作者简介:一名在后端领域学习,并渴望能够学有所成的追梦人。 🚁 个人主页:不 良 🔥 系列专栏:🛸C++  🛹Linux 📕 学习格言:博观而约取,厚积而薄发 🌹 欢迎进来的小伙伴,如果小伙伴们在学习的过程中,发现有需要纠正的地方,烦请指正,希望能够与诸君一同

    2024年02月15日
    浏览(28)
  • 【C++】:string的模拟实现

    朋友们、伙计们,我们又见面了,本期来给大家解读一下有关string的模拟实现,如果看完之后对你有一定的启发,那么请留下你的三连,祝大家心想事成! C 语 言 专 栏: C语言:从入门到精通 数据结构专栏: 数据结构 个  人  主  页 : stackY、 C + + 专 栏   : C++ Linux 专

    2024年02月08日
    浏览(28)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包