【C++进阶】深入STL之string:模拟实现走进C++字符串的世界

2024-06-04 1848阅读

📝个人主页🌹:Eternity._

⏩收录专栏⏪:C++ “ 登神长阶 ”

🤡往期回顾🤡:C++模板入门

🌹🌹期待您的关注 🌹🌹

【C++进阶】深入STL之string:模拟实现走进C++字符串的世界 第1张

【C++进阶】深入STL之string:模拟实现走进C++字符串的世界 第2张

❀STL之string

  • 📒1. string类的成员变量
  • 📒2. string的构造函数
    • 🎈无参的构造函数
    • 🎩带参的构造函数
    • 📒3. string的析构函数
    • 📒4. string的拷贝构造函数
      • 🔥 浅拷贝
      • 💧 深拷贝
      • 📒5. string类的运算符重载
      • 📒6. string容量相关函数
      • 📒7. string常用函数模拟
        • ⭐查找
        • ⭐ 添加
        • 📒8. 总结

          前言:在C++中,string是一个极其重要且常用的类,它为我们提供了丰富的字符串操作功能。然而,了解其背后的实现原理,不仅可以帮助我们更好地使用它,还能让我们对C++的内存管理、模板编程等有更深入的理解。本文将带你走进C++字符串的世界,通过模拟实现一个简单的string类,来探索其内部机制

          模拟实现string类,最主要是实现string类的构造、拷贝构造、赋值运算符重载以及析构函数


          📒1. string类的成员变量

          首先我们要先搞清楚string的成员变量,我们清楚string类在底层实际上就是一个字符指针,在模拟实现string之前,我们创建一个属于自己的命名空间来与库里面的区分

          namespace pxt
          {
          	class string
          	{
          	public:
          		const char* c_str() const // 为了能更好的实现,我们提前实现以下c.str
          		{
          			return _str;
          		}
          	private:
          		// 成员变量
          		char* _str; // 指向一段空间的指针
          		size_t _size; // 有效字符串长度
          		size_t _capacity; // 空间总大小
          	};
          }
          

          📒2. string的构造函数

          🎈无参的构造函数

          string()
          	:_str(new char[1]{ '

          🎩带参的构造函数

          ' }) ,_size(0) , _capacity(0) {}

          注意:在调用无参的构造函数时,库里面并不只是开了空间,它还干了其他事情,所以我们在自己模拟现实时,一定不能用nullptr去初始化,否则就会出错,因此我们放一个'\0'进去!

          std::string无参构造:

          【C++进阶】深入STL之string:模拟实现走进C++字符串的世界 第3张


          string(const char* str = "")
          	:_size(strlen(str))
          	, _capacity(_size)
          {
          	_str = new char[_capacity + 1];
          	strcpy(_str, str);
          }
          

          📒3. string的析构函数

          在带参的构造函数因为常量字符串最后自带了一个'\0',因此我们什么都不用带


          ~string()
          {
          	delete[] _str;
          	_str = nullptr;
          	_size = _capacity = 0;
          }
          

          📒4. string的拷贝构造函数

          string的析构函数非常简单,只需要将空间用delete释放,并且将各个指针置为空,将空间大小变为0


          🔥 浅拷贝

          // 拷贝构造
          string(const char* str = "")
          {
          	if (nullptr == str)
          	{
           		return;
           	}
           	_str = new char[strlen(str) + 1];
           	strcpy(_str, str);
          }
          // 测试
          void test_string()
          {
           	string s1("hello world");
           	string s2(s1);
          }
          

          首先我们来看一段拷贝构造的模拟实现:

          💧 深拷贝

          【C++进阶】深入STL之string:模拟实现走进C++字符串的世界 第4张

          为什么会引发异常呢?

          【C++进阶】深入STL之string:模拟实现走进C++字符串的世界 第5张

          【C++进阶】深入STL之string:模拟实现走进C++字符串的世界 第6张

          我们发现s1和s2都指向都一块空间,在释放时同一块空间是不可以被释放多次的,从而引起了崩溃,而这就是浅拷贝!

          浅拷贝: 也称位拷贝,编译器只是将对象中的值拷贝过来。如果对象中管理资源,最后就会导致多个对象共享同一份资源,当一个对象销毁时就会将该资源释放掉,而此时另一些对象不知道该资源已经被释放,以为还有效,所以当继续对资源进项操作时,就会发生发生了访问违规,

          可以采用深拷贝解决浅拷贝问题,即:每个对象都有一份独立的资源,不要和其他对象共享


          // 我们用s作为s1的别名
          string(const string& s)
          {
          	_str = new char[s._capacity + 1];
          	strcpy(_str, s._str);
          }
          

          📒5. string类的运算符重载

          【C++进阶】深入STL之string:模拟实现走进C++字符串的世界 第7张

          深拷贝:每个对象都有一份独立的资源,不要和其他对象共享

          注意: 关于浅拷贝一定要引起重视!


          // 传统写法
          string& operator=(const string& s)
          {
          	if (this != &s)
          	{
          		char* tmp = new char[s._capacity + 1]; // 存放'

          ⭐ 添加

          ' strcpy(tmp, s._str); delete[] _str; _str = tmp; _size = s.size(); _capacity = s.capacity(); } return *this; } // 现代写法 string& operator=(string s) { swap(_str, s._str); // swap库中存在,可以直接使用 return *this; }

          operator=

          在operator=上,我们有两种写法

          // 尾插单个字符
          void push_back(char ch)
          {
          	if (_size == _capacity)
          	{
          		reserve(_capacity == 0 ? 4 : _capacity * 2);
          	}
          	_str[_size] = ch;
          	++_size;
          	_str[_size] = '

          📒8. 总结

          '; } // 插入字符串 void append(const char* str) { size_t len = strlen(str); if (_size + len > _capacity) { reserve(_size + len); } strcpy(_str + _size, str); _size += len; } string& operator+=(char ch) { push_back(ch); return *this; } string& operator+=(const char* str) { append(str); return *this; }

          传统写法

          • 传统写法函数的运用引用传参,通过创建中间变量,并开辟空间然后将参数拷贝进中间变量,再把这个中间变量的地址传给this,从而实现了operator=的功能

            现代写法

            • 现代写法使用了库中的swap函数,从而让函数达到一个简洁的目的,该函数的参数是一个临时拷贝变量,深拷贝后,通过swap交换即可

              operator return strcmp(_str, s._str)

              因为在添加中+=既可以添加字符也可以添加字符串,往往在日常中的使用频率是最高的,所以推荐大家使用+=来代替push_back和append


              经过对STL中string的深入探索与模拟实现,我们仿佛揭开了一个隐藏在C++深处的奇妙世界。这个旅程不仅让我们对string这一基础数据类型有了更为深刻的理解,也让我们领略了STL背后的设计理念与精巧实现,让我们携手共进,共同走进C++字符串的奇妙世界!

              【C++进阶】深入STL之string:模拟实现走进C++字符串的世界 第8张

              谢谢大家支持本篇到这里就结束了,祝大家天天开心!

              【C++进阶】深入STL之string:模拟实现走进C++字符串的世界 第9张


    免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们,邮箱:ciyunidc@ciyunshuju.com。本站只作为美观性配图使用,无任何非法侵犯第三方意图,一切解释权归图片著作权方,本站不承担任何责任。如有恶意碰瓷者,必当奉陪到底严惩不贷!

    目录[+]