你不能不知道的string类的基础知识

news2024/11/15 23:32:36

文章目录

  • 前言
  • string类
    • 1. 为什么要学习string类
      • 1.1 C语言中的字符串不够好用
    • 2. 标准库中的string类
      • 2.1 string类(了解)
      • 2.2 string类的常用接口说明
      • 2.3 string类对象的容量操作
      • 2.4string类对象的访问及遍历操作
      • 2.5 string类对象的修改操作
      • 2.6 string类非成员函数
      • 2.7 vs和g++下string结构的说明
    • 3. 拷贝问题
      • **浅拷贝:**
      • **深拷贝:**
      • 写时拷贝(了解)
  • 后记

前言

本篇将学习string类的基础知识

🕺作者: 迷茫的启明星
专栏:《C++初阶》
相关string类的的题博客:
《leetcode43. 字符串相乘》
《leetcode415. 字符串相加》
《leetcode17. 电话号码的字母组合》

😘欢迎关注:👍点赞🙌收藏✍️留言

🏇码字不易,你的👍点赞🙌收藏❤️关注对我真的很重要,有问题可在评论区提出,感谢阅读!!!

持续更新中~

string类

1. 为什么要学习string类

1.1 C语言中的字符串不够好用

C语言中,字符串是以’\0’结尾的一些字符的集合,为了操作方便,C标准库中提供了一些str系列的库函数,但是这些库函数与字符串是分离开的,不太符合OOP的思想,而且底层空间需要用户自己管理,稍不留神可能还会越界访问。

2. 标准库中的string类

2.1 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;

2.2 string类的常用接口说明

想更多了解的可以看这里:http://www.cplusplus.com

相关比较常用的实现我都在这篇博客中实现过了(☞《从零开始实现 std::string:让你更深入地了解字符串的本质》)

  1. string类对象的常见构造
(constructor)函数名称功能说明
string() (重点)构造空的string类对象,即空字符串
string(const char* s) (重点)用C-string来构造string类对象
string(size_t n, char c)string类对象中包含n个字符c
string(const string&s) (重点)拷贝构造函数
string (const string& str, size_t pos, size_t len = npos);取前一个字符串的一段
string (const char* s, size_t n);取前面一个字符串的前n个字符
void Teststring1()
{
    string s1; 
    // 构造空的string类对象s1
    string s2("hello world!!!"); 
    // 用C格式字符串构造string类对象s2
    string s3(s2); 
    // 拷贝构造s3
    string s4(s2, 6, 5);
    //从坐标6开始,取长度为5的一段字符,如果第三个参数len大于后面字符长度,有多少拷贝多少拷贝到结尾
    string s5("hello world", 5);
    //取前面字符串的前5个字符“hello”
    string s6(100, 'x');
    //构成一个含100个x字符的字符串
}

2.3 string类对象的容量操作

函数名称功能
size返回字符串有效字符长度
length返回字符串有效字符长度
capacity返回空间总大小
empty检测字符串释放为空串,是返回true,否则返回false
clear清空有效字符
reserve为字符串预留空间
resize将有效字符的个数该成n个,多出的空间用字符c填充

注意:

  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不会改变容量大小。

示例:

#include<iostream>
using namespace std;
int main()
{
	string s("1314520");
	cout << "s的长度:"<<s.size() << endl;
	cout << "s的长度:" << s.length() << endl;
	cout << "s的容量:" << s.capacity() << endl;
	cout << "s是否为空:" << s.empty() << endl;
	s.clear();//清除字符
	cout << s << endl;
	s="1314520";//重新设置字符串
	s.reserve(520);//设置空间
	cout << "重新设置后s的容量:"<<s.capacity() << endl;
	s.resize(13);//设置有效字符串的长度,多余的用第二个参数填补,默认为""
	cout << "重新设置后s的长度:" << s.size() << endl;
	s.resize(19,'s');//设置填充值为's'
	cout << "重新设置后s的长度:" << s.size() <<" ""重新设置后的s:"<<s << endl;
	return 0;
}

输出:

在这里插入图片描述

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

函数名称功能说明
operator[]返回pos位置的字符,const string类对象调用
begin / endbegin获取一个字符的迭代器 + end获取最后一个字符下一个位置的迭代器
rbegin / rendbegin获取一个字符的迭代器 + end获取最后一个字符下一个位置的迭代器
范围forC++11支持更简洁的范围for的新遍历方式

示例:

#include<iostream>
using namespace std;
int main()
{
	string s("1314520");
	cout << s[2] << endl;
	reverse(s.begin(), s.end());//翻转字符串
	cout <<s<<endl;
	reverse(s.rbegin(), s.rend());//再次翻转
	cout << s << endl;
	for (auto ch : s)
	{
		cout << ch;
	}
	return 0;
}

输出:

在这里插入图片描述

2.5 string类对象的修改操作

函数名称功能
push_back在字符串后尾插字符c
append在字符串后追加一个字符串
operator+=在字符串后追加字符串str
c_str返回C格式字符串
find / npos从字符串pos位置开始往后找字符c,返回该字符在字符串中的位置
rfind从字符串pos位置开始往前找字符c,返回该字符在字符串中的位置
substr在str中从pos位置开始,截取n个字符,然后将其返回
insert在str中从pos位置开始,插入字符或字符串(常用)

注意:

  1. 在string尾部追加字符时,s.push_back© / s.append(1, c) / s += 'c’三种的实现方式差不多,一般情况下string类的+=操作用的比较多,+=操作不仅可以连接单个字符,还可以连接字符串。
  2. 对string操作时,如果能够大概预估到放多少字符,可以先通过reserve把空间预留好。

示例:

#include<iostream>
using namespace std;
int main()
{
	string s("1314520");
	cout << "原来的s:" << s << endl;
	s.push_back('a');
	cout << "尾插后的s:" << s<<endl;
	s += " 3.141559";
	cout << "追加字符串后的s:" << s << endl;
	cout << "输出C格式字符串:"<<s.c_str() << endl;//输出C格式字符串
	cout << s.find('5') << endl;//从左开始往后找字符c,返回该字符在字符串中的位置
	cout<< s.rfind('5') << endl;//从右开始往后找字符c,返回该字符在字符串中的位置
	cout << s.substr(4,3) << endl;//从坐标4往后截取3个字符
	cout << s.insert(0, "天青色等烟雨");//插入字符串
	return 0;
}

输出:

在这里插入图片描述

2.6 string类非成员函数

函数功能
operator+尽量少用,因为传值返回,导致深拷贝效率低
operator>>输入运算符重载
operator<<输出运算符重载
getline获取一行字符串
relational oprators大小比较

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

注意:下述结构是在32位平台下进行验证,32位平台下指针占4个字节。

  • vs下string的结构
    string总共占28个字节,内部结构稍微复杂一点,先是有一个联合体联合体用来定义string中字符串的存储空间
    • 当字符串长度小于16时,使用内部固定的字符数组来存放
    • 当字符串长度大于等于16时,从堆上开辟空间
union _Bxty
{ // storage for small buffer or pointer to larger one
    value_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;
    };
    
    • 指向堆空间的指针,用来存储字符串。

3. 拷贝问题

浅拷贝:

浅拷贝:也称位拷贝,编译器只是将对象中的值拷贝过来。

如果对象中管理资源,最后就会导致多个对象共享同一份资源,

当一个对象销毁时就会将该资源释放掉,

而此时另一些对象不知道该资源已经被释放,以为还有效,

所以当继续对资源进项操作时,就会发生发生了访问违规。

所以与资源管理(空间分配)有关的拷贝一定要注意深浅拷贝的情况,判断是否要自己写拷贝函数,也就是深拷贝。

深拷贝:

如果一个类中涉及到资源的管理,其拷贝构造函数、赋值运算符重载以及析构函数必须要显式给出。一般情况都是按照深拷贝方式提供。

比如说:

#include<iostream>
using namespace std;
int main()
{
    string s1;
    string s2="chatgpt";
    s1=s2;
    return 0;
}

它的实现原理是上面呢?

实际情况如下:

在这里插入图片描述

每个String类对象都要用空间来存放字符串,而s1需要s2拷贝出来,这时候就要用到深拷贝了,它需要给每个对象分配独立的资源,保证他们不会因为共享资源而造成多次释放而造成程序奔溃

写时拷贝(了解)

在这里插入图片描述

写时拷贝就是一种拖延症,是在浅拷贝的基础之上增加了引用计数的方式来实现的。
引用计数:用来记录资源使用者的个数。在构造时,将资源的计数给成1,每增加一个对象使用该资源,就给计数增加1,当某个对象被销毁时,先给该计数减1,然后再检查是否需要释放资源,如果计数为1,说明该对象时资源的最后一个使用者,将该资源释放否则就不能释放,因为还有其他对象在使用该资源。

后记

感谢大家支持!!!

respect!

下篇见!

在这里插入图片描述

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

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

相关文章

《花雕学AI》大揭秘:ChatGPT 如何让你的聊天机器人更智能、更有趣、更有用

你是否想过有一个可以和你聊天、陪你玩耍、帮你学习、给你创意的机器人&#xff1f;如果你的答案是肯定的&#xff0c;那么你一定会喜欢 ChatGPT。 ChatGPT 是一个基于 GPT-3 或者 GPT-4 技术的聊天机器人&#xff0c;可以与人类进行自然和流畅的对话。GPT-4 是目前最先进的自…

[Gitops--8]微服务前置中间件部署

微服务前置中间件部署 1. MySQL主从 1.1 创建持久化存储 使用project-admin账号 进入sangomall项目 [存储],[存储卷],sangomall-mysql-master-pvc storageclass创建详见K8s集群中部署KubeSphere 2.1章节 在k8s环境下可以看到这个sc rootks-master:~/yaml# kubectl get sc NA…

Cadence Allegro(1):手动PCB封装制作(以TYPE-C 16Pin为例)

Cadence Allegro 16.6&#xff08;1&#xff09;&#xff1a;手动PCB封装制作&#xff08;以TYPE-C 16Pin为例&#xff09; 前提摘要&#xff1a; PCB设计软件版本&#xff1a; 焊盘设计 &#xff1a;Pad Designer 16.6PCB设计 &#xff1a;PCB Editor 16.6 个人说明&#xf…

【HarmonyOS】自定义组件之ArkUI实现通用标题栏组件

【关键字】 标题栏、常用内置组件整合、ArkUI、自定义组件 1、写在前面 在上一篇文章中我们通过Java语言实现了一个通用的标题栏组件&#xff0c;有需要的可以看下&#xff0c;文章地址&#xff1a; 华为开发者论坛 现在很多朋友都已经转战ArkTS语言了&#xff0c;那么今天…

项目集的定义及管理

一、什么是项目集 项目集是相互关联且被协调管理的项目、子项目集和项目集活动&#xff0c;以便获得分别管理所无法获 得的效益。 以项目集的形式管理项目、子项目集及项目集活动能确保项目集组件的战略和工作计划根据各组 件的成果做出相应调整&#xff0c;或者按照发起组织的…

PWM控制舵机

文章目录 运行环境&#xff1a;1.1 原理1)A板原理图2)PA8引脚配置3)定时器Timers配置 2.1代码解释1)定时器1初始化函数2)启动定时器中断3)启动PWM/设置占空比4)launch设置5) 编译调试 3.1实验效果 运行环境&#xff1a; ubuntu18.04.melodic 宏基暗影骑士笔记本 stm32f427IIH6…

JAVA常用的工具类

文章目录 1 集合工具类1.1 java.util.Collections1.1.1 基本操作1.1.2 转换线程安全集合 1.2 org.springframework.util.CollectionUtils1.3 org.apache.commons.collections.CollectionUtils1.4 org.apache.commons.lang.ArrayUtils1.5 org.apache.commons.lang3.ArrayUtils1.…

[Java] 中的具体集合

文章目录 集合根接口List列表&#xff08;线性表&#xff09;Queue & Deque双端队列 Set集合HashSet源码应用 TreeSet源码 Map映射Map的底层实现HashMapLinkedHashMapTreeMap Maps methodcompute()merge()replace()remove() Stream流Collections工具类 集合表示一组对象&am…

Reactor 第九篇 WebFlux重构个人中心,效果显著

1 重构背景 原有的开发人员早已离职&#xff0c;代码细节没人知道&#xff0c;经过了一段时间的维护&#xff0c;发现有以下问题&#xff1a; 个人中心系统的特征就是组装各个业务的接口&#xff0c;输出个人中心业务需要的数据&#xff0c;整个系统调用了几十个第三方业务线的…

moment在vue的使用

第一步&#xff1a;安装moment npm install moment --save-dev第二步&#xff1a;在使用moment的地方引入moment import moment from "moment"; monent的方法&#xff1a; &#xff08;1&#xff09;moment([日期])&#xff1a; 获取当前日期或指定日期&#xff…

pytorch学习率设置——optimizer.param_groups、对不同层设置学习率、动态调整学习率。

文章目录 前言1、关于optimizer.param_groups2、设置学习率3、optim 提供的优化器 前言 我的需求&#xff1a;我需要在yolov7中更改其中一层的学习率&#xff0c;但yolov7的学习率是随着eporch的变化动态变化的。 1、关于optimizer.param_groups “param_groups” 是 Pytorch…

LeetCode1047. 删除字符串中的所有相邻重复项

1047. 删除字符串中的所有相邻重复项 给出由小写字母组成的字符串 S&#xff0c;重复项删除操作会选择两个相邻且相同的字母&#xff0c;并删除它们。 在 S 上反复执行重复项删除操作&#xff0c;直到无法继续删除。 在完成所有重复项删除操作后返回最终的字符串。答案保证唯一…

RabbitMQ 工作队列模型(任务队列)

任务模型 概念 ​ 当消息处理比较耗时的时候&#xff0c;可能生产消息的速度大于消费的速度&#xff0c;长此以往&#xff0c;就会导致消息堆积&#xff0c;无法及时处理&#xff0c;此时可以使用任务模型&#xff0c;当多个消费者绑定一个队列&#xff0c;共同消费其中的消息…

认识JSP

什么是JSP? JSP&#xff08;Java Server Pages&#xff09;是一种类似于HTML的标记语言&#xff0c;用于创建动态Web页面。与HTML不同的是&#xff0c;JSP页面中可以嵌入Java代码&#xff0c;由Web服务器在动态页面中生成HTML代码&#xff0c;从而实现Web应用程序的前端交互效…

scratch求和 中国电子学会图形化编程 少儿编程 scratch编程等级考试四级真题和答案解析2023年3月

目录 scratch求和 一、题目要求 1、准备工作 2、功能实现 二、案例分析

node之Express

目录 Express简介 安装 创建基本的Web服务器 托管静态资源 以上述案例为基础访问静态资源的路径为&#xff1a;http://127.0.0.1:8080/xxx.html 托管多个静态资源目录 路由的概念 路由的匹配过程 模块化路由 模块化路由案例 中间件的概念 定义中间件函数例 全局生…

AI助阵,领先创新丨智能评价分析·数字员工,开启顶级消费者体验新篇章!

GPT-4作为人工智能时代发展道路上的里程碑&#xff0c;以其惊人的多模态大模型能力吸引了众多零售消费品牌的关注&#xff0c;利用AI技术解决客户复杂业务问题&#xff0c;成为推动行业提质增效的重要途径。实在智能是国内首个生成式AI标准编写单位&#xff0c;始终坚持AI赋能商…

各种常用字符编码详解【图文教程】,Unicode 是一个编码规范,并不是一个具体的编码

文章目录 常见编码的比较&#xff0c;各个编码中各字符占用(字节数):简体中文编码发展史&#xff0c;编码出现时间和涵盖范围UTF-8、unicode与GBK编码转化一问一答其他ASCII表 参考文档 常见编码的比较&#xff0c;各个编码中各字符占用(字节数): 编码英文中文&#xff08;简体…

数说热点 | 跟着《长月烬明》起飞,今年各地文旅主打的就是一个听劝

近日&#xff0c;随着热播剧《长月烬明》的爆火&#xff0c;蚌埠、宣城、敦煌等多个与剧情梦幻联动的宝藏城市被带飞&#xff0c;各地热心网友也纷纷催促自家文旅局赶紧“蹭飞”&#xff0c;《长月烬明》以一己之力打造了影视文旅融合的新样板。 仙偶剧特效天花板&#xff0c;…

SpringCloud------代码demo(二)

SpringCloud------代码demo&#xff08;二&#xff09; 编码实操 以订单——支付微服务模块作为基础&#xff0c;开始逐渐扩充 微服务架构编码构建 1.约定 > 配置 > 编码 2.IDEA新建project工作空间 3.Rest微服务工程构建 总父工程 POM project module 首先创建maven项…