初始《string》及手搓模拟实现《string》

目录

前言:

为什么学习string类?

标准库中的string类

1. string类对象的常见构造

​编辑

2. string类对象的容量操作

​编辑

3. string类对象的访问及遍历操作

 4. string类对象的修改操作

5. string类非成员函数

 vs和g++下string结构的说明

vs下string的结构

g++下string的结构

模拟实现string:

构造函数:

深浅拷贝:

浅拷贝:

深拷贝:

​编辑

传统写法与现代写法:

s2(s1)

s2 = s1 

 输入:

总结:


前言:

在之前的学习中,我们初步了解到了模板的概念,而接下来又对于C++的标准模板库(STL)也有了基本的概念。对于C++的武器,我们不得不进行学习,日后有了这些STL武器的帮助,对于大部分题目我们都能游刃有余。

 

为什么学习string类?

C语言中,字符串是以'\0'结尾的一些字符的集合,为了操作方便,C标准库中提供了一些str系列的库函数,但是这些库函数与字符串是分离开的,不太符合OOP的思想,而且底层空间需要用户自己管理,稍不留神可能还会越界访问。
在OJ中,有关字符串的题目基本以string类的形式出现,而且在常规工作中,为了简单、方便、快捷,基本都使用string类,很少有人去使用C库中的字符串操作函数。

我们可以将string理解为——数组顺序表


标准库中的string类

1. 字符串是表示字符序列的类
2. 标准的字符串类提供了对此类对象的支持,其接口类似于标准字符容器的接口,但添加了专门用于操作单字节字符字符串的设计特性。
3. string类是使用char(即作为它的字符类型,使用它的默认char_traits和分配器类型(关于模板的更多信息,请参阅basic_string)。
4. string类是basic_string模板类的一个实例,它使用char来实例化basic_string模板类,并用char_traits和allocator作为basic_string的默认参数(根于更多的模板信息请参考basic_string)。
5. 注意,这个类独立于所使用的编码来处理字节:如果用来处理多字节或变长字符(如UTF-8)的序列,这个类的所有成员(如长度或大小)以及它的迭代器,将仍然按照字节(而不是实际编码的字符)来操作。
总结:
1. string是表示字符串的字符串类
2. 该类的接口与常规容器的接口基本相同,再添加了一些专门用来操作string的常规操作。
3. string在底层实际是:basic_string模板类的别名,typedef basic_string<char, char_traits, allocator>string;
4. 不能操作多字节或者变长字符的序列。
在使用string类时,必须包含#include头文件以及using namespace std;

1. string类对象的常见构造

2. string类对象的容量操作

注意:
1. size()与length()方法底层实现原理完全相同,引入size()的原因是为了与其他容器的接口保持一
致,一般情况下基本都是用size()。

2. clear()只是将string中有效字符清空,不改变底层空间大小。

3. resize(size_t n) 与 resize(size_t n, char c)都是将字符串中有效字符个数改变到n个,不同的是当字符个数增多时:resize(n)用0来填充多出的元素空间,resize(size_t n, char c)用字符c来填充多出的元素空间。注意:resize在改变元素个数时,如果是将元素个数增多,可能会改变底层容量的大
小,如果是将元素个数减少,底层空间总大小不变。

4. reserve(size_t res_arg=0):为string预留空间,不改变有效元素个数,当reserve的参数小于
string的底层空间总大小时,reserver不会改变容量大小。

 

3. string类对象的访问及遍历操作

 

 4. string类对象的修改操作

注意:
1. 在string尾部追加字符时,s.push_back(c) 或 s.append(1, c) 或 s += 'c'三种的实现方式差不多,一般情况下string类的+=操作用的比较多,+=操作不仅可以连接单个字符,还可以连接字符串。

2. 对string操作时,如果能够大概预估到放多少字符,可以先通过reserve把空间预留好。

 

5. string类非成员函数

 vs和g++下string结构的说明

vs下string的结构

string总共占28个字节,内部结构稍微复杂一点,先是有一个联合体,联合体用来定义string中字
符串的存储空间:

  • 当字符串长度小于16时,使用内部固定的字符数组来存放
  • 当字符串长度大于等于16时,从堆上开辟空间
union _Bxty
{     // storage for small buffer or pointer to larger onevalue_type _Buf[_BUF_SIZE];pointer _Ptr;char _Alias[_BUF_SIZE]; // to permit aliasing
} _Bx;

这种设计也是有一定道理的,大多数情况下字符串的长度都小于16,那string对象创建好之后,内
部已经有了16个字符数组的固定空间,不需要通过堆创建,效率高。

其次:还有一个size_t字段保存字符串长度,一个size_t字段保存从堆上开辟空间总的容量
最后:还有一个指针做一些其他事情。
故总共占16+4+4+4=28个字节

 

g++下string的结构

G++下,string是通过写时拷贝实现的,string对象总共占4个字节,内部只包含了一个指针,该指
针将来指向一块堆空间,内部包含了如下字段:

  • 空间总大小
  • 字符串有效长度
  • 引用计数
  • 指向堆空间的指针,用来存储字符串
struct _Rep_base
{size_type _M_length;size_type _M_capacity;_Atomic_word _M_refcount;
};

 

模拟实现string:

构造函数:

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

 

  • 不可以将缺省值设置成nullptr,strlen(str)对于str指针解引用,遇到’\0’终止,解引用NULL会报错
  • 将缺省值设置成一个空字符串,结尾默认为’\0’

深浅拷贝:

 上述String类没有显式定义其拷贝构造函数与赋值运算符重载,此时编译器会合成默认的,当用s1构造s2时,编译器会调用默认的拷贝构造。最终导致的问题是,s1、s2共用同一块内存空间,在释放时同一块空间被释放多次而引起程序崩溃,这种拷贝方式,称为浅拷贝

浅拷贝:

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

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

深拷贝:

传统写法与现代写法:

s2(s1)

        //s2(s1)//// 传统写法string(const string& s){_size = s._size;_capacity = s._capacity;strcpy(_str, s._str);}// 现代写法string(const string& s){string tmp(s._str);swap(tmp);}

s2 = s1 

//s2 = s1(赋值 ——> 构造 + 拷贝), 因此不同于string(const string& s), 
//我们需要创建一个临时变量// 传统写法string& operator=(const string& s){char* tmp = new char[s._size + 1];strcpy(tmp, s._str);delete[] _str;_str = tmp;_size = s._size;_capacity = s._capacity;return *this;}// 现代写法string& operator=(string s) // 形参是实参的一份临时拷贝{swap(s);return *this;}

 输入:

istream& operator>>(istream& in, string& s){s.clear();char ch;//in >> ch;ch = in.get();// cin 读字符的时候取不到“空格”和“回车”,// 所有我们运用cin.get(),提取一个字符char buff[128];size_t i = 0;while (ch != ' ' && ch != '\n'){buff[i++] = ch;// [0,126]if (i == 127){buff[127] = '\0';s += buff;i = 0;}ch = in.get();}if (i > 0){buff[i] = '\0';s += buff;}return in;}istream& getline(istream& in, string& s){s.clear();char ch;//in >> ch;ch = in.get();char buff[128];size_t i = 0;while (ch != '\n'){buff[i++] = ch;// [0,126]if (i == 127){buff[127] = '\0';s += buff;i = 0;}ch = in.get();}if (i > 0){buff[i] = '\0';s += buff;}return in;}

scanf 和 cin  基于 空格 和 回车加以区分

而对于我们想输入一个英文句子使用cin就难上加难,我们可以使用getline来输入英文句子,因为getline可以读取空格,而遇到回车就停下。

总结:

 以上就是string的部分内容,在这里我只对于重要的部分进行讲解,string这个库有许多自带的函数,下来可以自己动手尝试尝试实现。手搓string的完整代码在我的Gitee里面:
My_String_CSDN/My_String_CSDN/String.h · 无双/C_Plus_Plus_Acer - 码云 - 开源中国 (gitee.com)

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/783496.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

k8s1.28.8版本安装prometheus并持久化数据

本文参考 [k8s安装prometheus并持久化数据_/prometheus-config-reloader:-CSDN博客](https://blog.csdn.net/vic_qxz/article/details/119598466)前置要求: 已经部署了NFS或者其他存储的K8s集群. 这里注意networkpolicies网络策略问题&#xff0c;可以后面删除这个策略&#x…

LangChain使用本地LLM的简单实现

所用模型&#xff1a;stable-code-instruct-3b-Q8_0.gguf 下载链接&#xff1a;bartowski/stable-code-instruct-3b-GGUF Hugging Face 详细内容请查看&#xff1a;Introduction | &#x1f99c;️&#x1f517; Langchain 目录 LangChain 代码示例 LangChain LangChain…

再生式收音机填坑记

年前踩坑再生式收音机&#xff0c;还是得找机会把坑填上&#xff0c;最终选定了K8TND的方案&#xff0c;其实与Mr. Kitchen的也基本差不多。电路图如下&#xff1a; 实物图如下&#xff1a; 实际接收效果还不错&#xff0c;但是感觉频段上哪哪都是中国之声&#xff0c;对这种…

UE4_碰撞_碰撞蓝图节点——Line Trace For Objects(对象的线条检测)

一、Line Trace For Objects&#xff08;对象的线条检测&#xff09;&#xff1a;沿给定线条执行碰撞检测并返回遭遇的首个命中&#xff0c;这只会找到由Object types指定类型的对象。注意他与Line Trace By Channel(由通道检测线条&#xff09;的区别&#xff0c;一个通过Obje…

React系列之合成事件与事件处理机制

文章目录 React事件处理机制原生事件的事件机制事件代理&#xff08;事件委托&#xff09; 合成事件使用合成事件目的合成事件原生事件区别事件池 原生事件和React事件的执行顺序e.stopPropagation() React17事件机制的修改 React事件处理机制 react 事件机制基本理解&#xf…

时序预测 | Matlab实现CPO-BP冠豪猪算法优化BP神经网络时间序列预测

时序预测 | Matlab实现CPO-BP冠豪猪算法优化BP神经网络时间序列预测 目录 时序预测 | Matlab实现CPO-BP冠豪猪算法优化BP神经网络时间序列预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 1.Matlab实现CPO-BP冠豪猪算法优化BP神经网络时间序列预测&#xff08;完整源码…

Linux(CentOS7)安装软件方式(编译安装,yum,rpm)

目录 前言 安装方式 编译安装 下载 解压 安装 创建软链接 yum rpm 前言 在使用 CentOS 安装软件时&#xff0c;发现安装的方式有好几种&#xff0c;有官网下载 tar 包解压&#xff0c;然后自己编译安装的&#xff0c;也有直接通过 yum 命令一键安装的&#xff0c;还有…

力扣刷题Days29-第二题-70.爬楼梯(js)

只有学习&#xff0c;没有自己的思路解题哈哈哈 1&#xff0c;题目 假设你正在爬楼梯。需要 n 阶你才能到达楼顶。 每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢&#xff1f; 2&#xff0c;代码 这种解法的本质是斐波那契数列 /*** param {number} n* re…

appium辅助自动化工具-- Appium studio

这里我要给大家介绍一款appium辅助自动化测试工具appium studio&#xff0c;你没看错&#xff0c;不是android studio&#xff0c;也不是appium android studio&#xff0c;就是appium studio&#xff01; 下载地址&#xff1a; Appium Studio | Digital.ai Continuous Test…

探究ThreadLocal的魔数0x61c88647和Entry数组

探究ThreadLocal 下面有一个很重要的HASH_INCREMENT,他的值是0x61c88647 public class ThreadLocal<T> {/***ThreadLocals依赖于附加到每个线程的每线程线性探针哈希映射 (thread.threadLocals和inheritableThreadLocals)。ThreadLocal对象充当键&#xff0c;通过threa…

Visual Studio 2022 中VLD库如何安装

GitHub链接 Release v2.5.1 KindDragon/vld 点击可执行程序进行下载 点击可执行程序进行安装 双击打开 一直点击next即可完成安装&#xff08;不用在意安装路径&#xff0c;总共不到2MB&#xff09; 如果GitHub无法打开&#xff0c;可以私信我发你安装包直接安装

二维码门楼牌管理应用平台建设:实现民主参与的新途径

文章目录 前言一、二维码门楼牌管理应用平台的兴起二、投票表决功能的实现三、居民参与度的提升四、面临的挑战与前景展望 前言 在数字化时代&#xff0c;二维码技术的应用已经渗透到我们生活的方方面面。近期&#xff0c;二维码门楼牌管理应用平台的建设成为了社区治理的一大…

[flask]请求全局钩子

flask从入门到精通之钩子、异常、context、jinjia模板、过滤器 - 异步非阻塞 - 博客园 (cnblogs.com) 参考的这个博客&#xff0c;但有一个需要注意的是&#xff0c;最新版本的flask不知道是不是更新了还是怎么了&#xff0c;他的before_first_request不见了&#xff0c;如果继…

Linux非root用户安装mysql5.7

1、下载安装包MySQL :: Download MySQL Community Server 点击Archives 我下载的是5.7.27版本&#xff0c;linux主机直接选择linux-Generic即可&#xff0c;选择第一个包下载即可 2、安装mysql 解压 shell> tar xzvf mysql-5.7.31-linux-glibc2.12-x86_64.tar.gz shell&g…

抽象类和接口的简单认识

目录 一、抽象类 1.什么是抽象类 2.抽象类的注意事项 3.抽象类与普通类的对比 二、接口 1.接口的简单使用 2.接口的特性 3.接口的使用案例 4.接口和抽象类的异同 一、抽象类 所谓抽象类&#xff0c;就是更加抽象的类&#xff0c;也就是说&#xff0c;这个类不能具体描…

NFC RC522开发记录

文章目录 一、ID卡、IC卡(M1卡、CPU卡)的区别二、RC522读写操作1. 数据读写流程三、RC522驱动代码1. RC522 与 STM32 的接线图2. RC522.c3. RC522.h4. main.c一、ID卡、IC卡(M1卡、CPU卡)的区别 ID卡 :只存储了ID号,设备识别ID号,没有算法可言,容易复制,安全性低IC卡包含了…

机器学习——最优化模型

最优化模型的概述&#xff1a; 从某种程度上说&#xff0c;我们的世界是由最优化问题组成的。每一天&#xff0c;我们的生活都面临无数的最优化问题&#xff1a;上班怎么选择乘车路线&#xff0c;才能舒服又快速地到达公司&#xff1b;旅游如何选择航班和宾馆&#xff0c;既省…

不可变集合及Stream流

若希望某个数据是不可修改的&#xff0c;就可以考虑使用不可变集合&#xff0c;以提高安全性&#xff1b;&#xff08;JKD9之后才有&#xff09; List不可变集合&#xff1a; public static void main(String[] args) {/*创建不可变的List集合"张三", "李四&q…

conda 创建 python3.10.12 环境

conda 创建 python3.10.12 环境 介绍使用前置条件&#xff1a;安装 conda配置环境变量验证 Conda 安装结果创建环境&#xff1a;python激活 Anaconda 环境 验证 Python 版本。 介绍 Conda是一个开源的包管理和环境管理系统&#xff0c;由Continuum Analytics公司开发。它可以安…

批量爬取招聘网站【Boss直聘】上工作岗位的招聘信息

不管是学生还是工作的小伙伴&#xff0c;估计都对不同岗位工作几年的薪酬水平比较感兴趣。本文提供爬取招聘网站&#xff0c;获取某类工作招聘信息的实现逻辑和代码。具体的实施步骤是&#xff1a;明确爬取的招聘网站—确定爬取的工作城市—确定爬取的岗位—获取岗位的招聘子链…