C++ ------>std::string--->模拟实现__01
  L8iEHH07GzZb 2023年11月02日 32 0

各位好友,接下来 我们将向 String 模拟实现进行开战 !在本期, 会实现部分常见的 String 类的接口 !

下面, 我们将共同对 String  底层原理进行逐一剖析 !让我们一步步接近 String 类对象的本质与 面纱 !

下面来看源代码 : >

1.头文件 "String.h"

#include <iostream>

namespace UC
{
  class string
  {
  public:
    //迭代器实现
    typedef char* iterator;
    typedef const char* const_iterator;
    iterator begin()
    {
    	return _str;
    }
		iterator end()
    {
    	return _str + _size;
    }
    const_iterator begin() const
    {
      return _str;
    }
    const_iterator end() const
    {
    	return _str + _size;
    }
    string(const char* str = " ")
    {
      _size = strlen(str);
      _capacity = _size;
      strcpy(_str, str);
    }
    ~string()
    {
    	delete[]_str;
      _str = nullptr;
      _size = _capacity = 0;
    }
    size_t size() const
    {
    	return _size;
    }
    const char* c_str() const
    {
    	return _str;
    }
    char& operator[](size_t pos)
    {
    	return _str[pos];
    }
    const char& operator[](size_t pos) const
    {
    	return _str[pos];
    }
    //追加字符串
    void push_back(char ch)
    {
    	if(_size == _capacity)
      {
        reserve(_capacity == 0 ? 4 : _capacity * 2);	// 自定义扩容函数
      }
      
      _str[_size] = ch;
      
      ++_size;
      _str[_size] = '\0';
    }
    void append(const char* str)
    {
    	size_t len = strlen(str);
      if(len + _size > _capacity)
      {
      	reserve(len + _size);
      }
      
      strcpy(len + _str, str);
      _size += len;
    }
    //扩容
    void reverse(size_t n)
    {
      if(n > _capacity)
      {
    	char* tamp = new char[n + 1];
      strcpy(tamp, _str);
      delete[]_str;
      _str = nullptr;
      _str = tamp;
       _capacity = n;
      }
    }
    string& operator+=(char ch)
    {
      push_back(ch);
    	return *this;
    }
    string& operator+=(const char* str)
    {
      append(str);
    	return *this;
    }
    private:
    	size_t _size;
    	size_t _capacity;
    	char* _str;
  };
}

2.测试环节 "Test.cpp"

#include "String.h"

using std::cout;
using std::endl;

void test_01()
{
	UC::string T1("I like music !");
  cout << T1.c_str() << endl;
  
  //遍历
  for(size_t i = 0; i < T1.size(); i++)
  {
  	cout << T1[i] << " ";
  }
  cout << endl;
  
  //迭代器
  UC::string::iterator it = T1.begin();
  while(it != T1.end())
  {
  	cout << *it << " ";
    ++it;
  }
  cout << endl;
}
void test_02()
{
	UC::string T1("I like music !");
  cout << T1.c_str() << endl;
  
  T1.push_back(' ');
  T1.push_back('&');
  T1.append("$$$$$$$$$$$");
  cout << T1.c_str() <<endl;
}
void test_03()
(
	UC::string T1("I like music !");
  cout << T1.c_str() << endl;
  
  T1 += ' ';
  T1 ++ '*';
  T1 += ' '; 
  T1 ++ "$$$$$$$$";
  
  cout << T1.c_str() << endl;
)
int main()
{
	test_0x();
}

为了方便好友们, 有更好地观感体验, 现 附上有彩色的代码图样 !

A.头文件 "String"

C++ ------>std::string--->模拟实现__01_String__模拟实现


测试及运行 :>

(1)No.1

C++ ------>std::string--->模拟实现__01_String__模拟实现_02


(2)No.2

C++ ------>std::string--->模拟实现__01_String__模拟实现_03


(3)No.3

C++ ------>std::string--->模拟实现__01_String__模拟实现_04


下面, 进入解析环节 :>

------------------------------------>有关于初始化列表<-----------------------------------------

错误用法 :>

C++ ------>std::string--->模拟实现__01_String__模拟实现_05

C++ ------>std::string--->模拟实现__01_String__模拟实现_06

原因如下 :>

由于初始化列表 ------->初始化过程是按照私有域里面的变量进行的创建 

--------------------------------------------> 有序的初始化 (可以通过调试进行观察)

因此,开辟新空间过程, _capacity 是一个随机值, 而该随机值往往非常大;------>新空间的开辟并不合理 !


正确用法  :>

C++ ------>std::string--->模拟实现__01_String__模拟实现_07

内置类型 放在初始化列表 影响不大 与放在函数体中初始化都是一样的,但是 自定义类型会有所不同 

自定义类型不用去写, 会自动调用它的默认构造函数 自定义类型最好是放在初始化列表进行初始化 !

同时, 回顾一下 ----> 前段时间, 学习的 默认构造函数有哪几种形式 ?(三种)

---------------------------------->无参数 ~~~ 全缺省 ~~~ 不用写自动生成 <-------------------------------------


难点 一 : >

各位好友, 下面对 const 修饰限定进行回顾复习 : >

(1)const 成员函数


C++ ------>std::string--->模拟实现__01_String__模拟实现_08

C++ ------>std::string--->模拟实现__01_String__模拟实现_09

此处迭代器位置 :>

运用了 const 修饰符进行限定, 保证普通对象在调用的时候, 能够进行 平移操作 , 同时涉及 权限的缩小 !

C++ ------>std::string--->模拟实现__01_String__模拟实现_10


注意 : >const 实际上修饰该成员函数隐含的 this 指针(可以省略)

------------------------->表明该成员函数中 不能对类的任何成员进行修改 <--------------------------------

C++ ------>std::string--->模拟实现__01_String__模拟实现_11

C++ ------>std::string--->模拟实现__01_String__模拟实现_12


(2)const 形参 ~~ 实参 ---->调用 与传入

C++ ------>std::string--->模拟实现__01_String__模拟实现_13

------------>而此处 const 添加 为保证数据再 被写入的时候, 只能能够进行 读取, 不能被 修改 !

------------>--------->-------->同时, 涉及到类型匹配, 测试部分的实参环节,输入的是一个常量字符串 !


难点 二 : >size_t

C++ ------>std::string--->模拟实现__01_String__模拟实现_14


各位好友, 为何此处需要用到 size_t --->首先 size_t 是一个无符号的整形运算符 !

size_t int 都是 C++ 中的数据类型,但是它们有 不同之处size_t 是一种无符号整数类型,通常用于表示内存中对象的大小或数组的索引。而 int 是一种有符号整数类型,通常用于表示整数值。

由于 size_t 是无符号整数类型,因此它不能表示负数。而 int 可以表示负数。此外,size_t 的大小取决于编译器和操作系统,通常为 32 位或 64 位。而 int 的大小通常为 32 位。

由于 size_t 是无符号类型,因此 不会出现负数,但是在某些情况下可能会发生溢出

------------->当 size_t 类型的变量达到其最大值时,再增加 “ 1 ” 就会导致溢出

在大多数平台上,size_t 的最大值是 2^64-1 2^32-1,具体取决于编译器和操作系统。

例如,在一个 64 位系统上,如果一个 size_t 类型的变量已经达到了最大值 2^64-1,再进行加一操作就会导致变量的值变为 0,这就是溢出


难点 三 : >

----->有关于 模拟实现 string 构造函数

注意:> 空字符串 默认带有一个 结束字符串 '\0' 而结束位置必须有一个结束字符串 ‘\0’

C++ ------>std::string--->模拟实现__01_String__模拟实现_15

C++ ------>std::string--->模拟实现__01_String__模拟实现_16

注意上述 字符串的大小计算结果 :>

会发现结束字符 ‘\0’ 被当作了 无效字符处理, strlen()接口实现不会将 ‘\0’进行计算在内 !!

因此, 开辟 空间容纳大小的时候, 需要多开一个字节的空间, 将结束字符 ‘\0’ 包含在内 !毕竟字符串输入之后, 编译器会自动将 ‘\0’添加上 !如此才有  “_str = new char[_capacity + 1]”空间开辟 “+1”说法


下面展现 三种错误用法 : >

(1)缺省参数初始化 为 nullptr(空指针)

C++ ------>std::string--->模拟实现__01_String__模拟实现_17

C++ ------>std::string--->模拟实现__01_String__模拟实现_18

---------------------->错误写法 会使得读入字符串的时候,调用 strlen(str) 即会崩溃 <-------------------


(2)缺省参数初始化 结束字符 '\0'(画蛇添足)

C++ ------>std::string--->模拟实现__01_String__模拟实现_19

C++ ------>std::string--->模拟实现__01_String__模拟实现_20

----------------------------->此种写法结果是正确的, 但是非常不简洁 !<-----------------------------


(3)缺省参数位置 没有 const 

C++ ------>std::string--->模拟实现__01_String__模拟实现_21

------------------------>第二个原因 :实参字符串 是一个常量 !这点不可以忽视 !<-----------------------------


至此 ,本期博文到此结束 !下一期, 我们将继续探索 string 底层实现原理 !

------>模拟实现 string 插入(insert) 删除(erase) 寻找(find) !------->敬请期待 !‘’😊😊


【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2023年11月08日 0

暂无评论

L8iEHH07GzZb