【C++】STL- > string类(超详解!!!)

文章目录

  • 前言
  • 1、string类的出现
    • 1.1 C语言中的字符串
    • 1.2 平时使用
  • 2. 标准库中的string类
    • 2.1 string类的常用文档(重要)!!!!
    • 2.2 string类的常用接口说明(接口原型我这里就不展示了,文档中都有可以去文档中去查找)
      • 1. string类对象的常见构造
      • 2. string类对象的容量操作
      • 3. string类对象的访问及遍历操作
      • 4. string类对象的修改操作
      • 5. string类非成员函数
    • 2.3 关于string的练习题
  • 3. string类的模拟实现
    • 3.1 经典的string类问题
    • 3.2 浅拷贝
    • 3.3 深拷贝
      • 3.3.1 传统版写法的string类
      • 3.3.2 现代版写法的string类
    • 3.3 写时拷贝(了解)
    • 3.4 string类的模拟实现
  • 总结
  • 参考资料(都是一些很好的文章和文档搜索网站)


前言

提示:这里可以添加本文要记录的大概内容:

字符串是编程中非常重要的数据类型,用于存储和处理文本信息。在C++中,可以使用两种主要方式来表示和操作字符串:

  • C风格字符串:以空字符(‘\0’)结尾的字符数组,例如"Hello, world!"。这种方式比较传统,但存在一些缺点,例如不易于使用和不安全。
  • string类:C++标准模板库(STL)中提供的类,专门用于表示和操作字符串。它具有易于使用、安全等优点。
    本文将介绍C++ STL中的string类,包括其基本概念、使用方法、模拟实现以及扩展阅读等内容。

提示:以下是本篇文章正文内容,下面案例可供参考

1、string类的出现

1.1 C语言中的字符串

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

1.2 平时使用

在平时使用中,不管是学习还是工作都需要大量用到string,很少有人会用C库中的库函数去操作字符串,string类的出现不仅仅是为了弥补C语言的缺陷,也是为了让我们快速操作字符串

2. 标准库中的string类

2.1 string类的常用文档(重要)!!!!

在库中,甚至是string中的接口都是数量很大的,如果要求我们每一个接口都十分熟悉那显示是不可能的,那么就需要我们学习利用文档学习,下面给出一个常用文档

如果觉得页面卡顿或者是用着不习惯,也可能使用以前的旧版本,更加的简洁(标红处)
在这里插入图片描述

注意:在使用string类时,必须包含#include头文件以及using namespace std;

2.2 string类的常用接口说明(接口原型我这里就不展示了,文档中都有可以去文档中去查找)

1. string类对象的常见构造

在这里插入图片描述
主要考虑以下几个接口
在这里插入图片描述

#include <iostream>
#include <string>
using namespace std;
int main()
{string s1;//构造空的string类对象,即空字符串string s2("hello cplusplus!!!");//用C-string来构造string类对象string s3(s2);//拷贝构造函数cout << s1 << endl;cout << s2 << endl;cout << s3 << endl;return 0;
}

2. string类对象的容量操作

在这里插入图片描述

void testString2()
{string s1("hello cplusplus!!");size_t n = s1.size();cout << n << endl;cout << s1.capacity() << endl;cout << s1.empty() << endl;s1.clear();//清空字符串中的内容,使其成为空字符串,但是不会改变size的值和容量的值n = s1.size();cout << n << endl;cout << s1.capacity() << endl;cout << s1.empty() << endl;s1.reserve(100);//reserve在英文中的意思是预定的意思,相当于预定了你指定空间的容量n = s1.size();cout << n << endl;cout << s1.capacity() << endl;cout << s1.empty() << endl;s1.resize(20,'a');n = s1.size();cout << n << endl;cout << s1.capacity() << endl;cout << s1.empty() << endl;
}

注意:

  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 n = 0):为string预留空间,不改变有效元素个数,当reserve的参数小于string的底层空间总大小时,reserve不会改变容量大小。

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

这里的迭代器大家目前可以暂时理解为指针
在这里插入图片描述
上述图片的表述有一些错误,rbegin和rend和begin、end相反,他们是反着打印,获取的也是相反的(具体可以去之前提到的文档链接去查到内容即可)

void testString3()
{string s1("hello cplusplus!!");const string s2("hello cplusplus!!");cout << s1 << " " << s2 << endl;cout << s1[0] << " " << s2[0] << endl;s1[0] = 'a';//s2[0] = 'a';//这里会发生编译错误,因为const类型对象不能修改cout << s1<<endl;string s("hello,c++");//三种遍历方式://需要注意的是,以下三种方式除了遍历打印string对象,还可以适用于遍历修改string中的字符//另外,三种方式中,对于string而言,第一种方式使用的最多// 1. for+operator[]for(size_t i = 0; i < s.size(); i++){cout << s[i]<<" ";}cout << endl;// 2.迭代器(这种方式底层大家暂时先不用明白,先了解大概怎么用,了解用法)//string::iterator it = s.begin();auto it = s.begin();while (it != s.end()){cout << *it << " ";it++;}cout << endl;// 3.范围forfor (auto& ch : s){cout << ch << " ";}}

4. string类对象的修改操作

在这里插入图片描述

void testString4()
{string s1("hello_c++");string s2("-hhh");s1.push_back('a');cout << s1 << endl;s1.append(s2);cout << s1 << endl;s1.append("xxx");cout << s1 << endl;s1 += '\0';s1 += "111";cout << s1 << endl;const char* s = s1.c_str();cout << s << endl;size_t n = s1.find("111",1);cout << n << endl;n = s1.rfind("hhh",18 );cout << n << endl;string s3 = s1.substr(0, 3);cout << s3 << endl;
}

注意:

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

5. string类非成员函数

在这里插入图片描述

**void testString5()
{string s1("hello_cpp");string s3 = s1.substr(0, 3);cout << s3 << endl;s1 = s1 + s3;cout << s1 << endl;string s2;//operator>>(cin,s2);//cout << s2 <<endl;getline(cin,s2);cout << s2 << endl;cout << ("abc" > "bbb") << endl;
}
**

上面的几个接口大家了解一下,下面的OJ题目中会有一些体现他们的使用。string类中还有一些其他的
操作,这里不一一列举,大家在需要用到时不明白了查文档即可。

2.3 关于string的练习题

  1. 题目一
  2. 题目二
  3. 题目三
  4. 题目四
  5. 题目五
  6. 题目六
  7. 题目七
  8. 题目八
  9. 题目九
  10. 题目十
  11. 题目十一

3. string类的模拟实现

3.1 经典的string类问题

上面已经对string类进行了简单的介绍,大家只要能够正常使用即可。在面试中,面试官总喜欢让学生自己
来模拟实现string类,最主要是实现string类的构造、拷贝构造、赋值运算符重载以及析构函数。大家看下以
下string类的实现是否有问题?

class string
{
public:/*string():_str(new char[1]){*_str = '\0';}*///string(const char* str = "\0") 错误示范//string(const char* str = nullptr) 错误示范string(const char* str = ""){// 构造string类对象时,如果传递nullptr指针,认为程序非法,此处断言下if(nullptr == str){assert(false);return;}_str = new char[strlen(str) + 1];strcpy(_str, str);}~string(){if(_str){delete[] _str;_str = nullptr;}}private:char* _str;
};
// 测试
void Teststring()
{string s1("hello bit!!!");string s2(s1);
}

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

3.2 浅拷贝

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

3.3 深拷贝

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

在这里插入图片描述

3.3.1 传统版写法的string类

class string
{
public:string(const char* str = ""){// 构造string类对象时,如果传递nullptr指针,认为程序非法,此处断言下if (nullptr == str){assert(false);return;}_str = new char[strlen(str) + 1];strcpy(_str, str);}string(const string& s): _str(new char[strlen(s._str) + 1]){strcpy(_str, s._str);}string& operator=(const string& s){if (this != &s){char* pStr = new char[strlen(s._str) + 1];strcpy(pStr, s._str);delete[] _str;_str = pStr;}return *this;}~string(){if (_str){delete[] _str;_str = nullptr;}}private:char* _str;
};

3.3.2 现代版写法的string类

class string
{
public:string(const char* str = ""){if (nullptr == str)str = "";_str = new char[strlen(str) + 1];strcpy(_str, str);}string(const string& s): _str(nullptr){string strTmp(s._str);swap(_str, strTmp._str);}// 对比下和上面的赋值那个实现比较好?string& operator=(string s){swap(_str, s._str);return *this;}/*string& operator=(const string& s){if(this != &s){string strTmp(s);swap(_str, strTmp._str);}return *this;}*/~string(){if (_str){delete[] _str;_str = nullptr;}}private:char* _str;
};

3.3 写时拷贝(了解)

写时拷贝就是一种拖延症,是在浅拷贝的基础之上增加了引用计数的方式来实现的。

引用计数:用来记录资源使用者的个数。在构造时,将资源的计数给成1,每增加一个对象使用该资源,就给
计数增加1,当某个对象被销毁时,先给该计数减1,然后再检查是否需要释放资源,如果计数为1,说明该
对象时资源的最后一个使用者,将该资源释放;否则就不能释放,因为还有其他对象在使用该资源。

3.4 string类的模拟实现

查看完整代码

总结

本文介绍了C++ STL中的string类的基本概念和使用方法,包括:

  • string类的创建和初始化
  • 访问和修改字符串内容
  • 常用字符串操作函数
  • 模拟实现string类
  • 扩展阅读
    通过本文的学习,读者应该能够掌握string类的基本用法,并能够在实际编程中使用它来完成各种字符串操作。

参考资料(都是一些很好的文章和文档搜索网站)

  • C++ STL string类使用及实现详解: https://blog.csdn.net/xiang_bolin/article/details/136097284
  • 【C++】深入浅出STL之string类: https://blog.csdn.net/fire_cloud_1/article/details/131914378
  • std::string class in C++: https://www.geeksforgeeks.org/stdstring-class-in-c/
  • https://cplusplus.com/reference/string/string/

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

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

相关文章

前后端分离(delivery-management)部署文档

1. 前端项目:delivery-management 1.1. 前端项目打包 执行命令:npm run build 或者yarn run build,生成dist目录。 构建流程如下图: 1.2. 文件上传 将打包好的前端项目(dist目录),上传到服务器,并拷贝到nginx安装目录html目录下。 执行上传命令(sftp):put -r E:\…

展示用HTML编写的个人简历信息

展示用HTML编写的个人简历信息 相关代码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Document…

Windows 自带的 Linux 子系统(WSL)安装与使用

WSL官网安装教程&#xff1a; https://learn.microsoft.com/zh-cn/windows/wsl/install Windows 自带的Linux子系统&#xff0c;比用VM什么的香太多了。可以自己看官方教程&#xff0c;也可以以下步骤完成。 如果中间遇到我没遇到的问题百度&#xff0c;可以在评论区评论&#…

Redis(03)——发布订阅

基础命令 基于频道 publish channel message&#xff1a;将信号发送到指定的频道pubsub subcommand [argument [argyment]]&#xff1a;查看订阅或发布系统状态subscribe channel [channel]&#xff1a;订阅一个或多个频道的信息unsubscribe [channel [channel]]&#xff1a;退…

Java——Stream流的学习

在开发过程中&#xff0c;经常或忽略流的使用&#xff0c;导致用的不熟练&#xff0c;于是抽时间系统的学习下stream的使用&#xff0c;找了哔哩哔哩的教程跟着看看练练。 准备工作 创建Book、Aurhor实体类&#xff0c;初始化数据 public static List<Author> getAuth…

解锁文档处理新境界:ONLYOFFICE编辑功能为开发者带来新机遇

引言 ONLYOFFICE最新发布的文档8.0版本带来了一系列引人注目的功能和优化&#xff0c;为用户提供了更强大、更高效的在线编辑体验。这次更新涵盖了多个方面&#xff0c;包括PDF表单、RTL支持、单变量求解、图表向导以及插件界面设计更新等。这些新功能不仅提升了文档处理的便利…

职业资格高级执法考试试题及答案,分享几个实用搜题和学习工具 #知识分享#微信

作为当代大学生&#xff0c;我们常常面临着繁重的学业压力和众多的学习任务。在这个信息爆炸的时代&#xff0c;如何高效地进行搜题和学习成了我们迫切需要解决的问题。幸运的是&#xff0c;随着科技的不断进步&#xff0c;我们拥有了许多方便、实用的日常搜题和学习软件。 1.…

旗舰配置,巅峰性能 | 一文玩转铁威马 『F4-424 Pro』强大的Docker虚拟机功能【附产品开箱】

旗舰配置&#xff0c;巅峰性能 | 一文玩转铁威马 『F4-424 Pro』强大的Docker&虚拟机功能【附产品开箱】 哈喽小伙伴们&#xff0c;我是Stark-C~ 开篇 记得还在两个月之前&#xff0c;我为大家介绍了国产“开箱即用”的国民专业级NAS『铁威马』&#xff1a; &#x1f53…

idea代码review工具Code Review Helper使用介绍

之前在团队里面遇到一个关于代码review的问题&#xff0c;使用gitlab自己的还是facebook的Phabricator&#xff0c;很难看到整体逻辑&#xff0c;因为业务逻辑代码可能不在这次改动范围内&#xff0c;在去源库中找不好找。针对这个刚需&#xff0c;在网上找了一个idea的代码工具…

kali安装awvs报错error creating the database

修改host文件 vim /etc/hosts 加入 127.0.0.1 kali 重启再安装即可解决

软件实例分享,操作简单美发店会员登记记账本vip会员管理系统软件教程

软件实例分享&#xff0c;操作简单美发店会员登记记账本vip会员管理系统软件教程 一、前言 以下软件程序教程以 佳易王美发店会员管理系统软件V16为例说明 软件文件下载可以点击最下方官网卡片——软件下载——试用版软件下载 1、新会员可以直接使用手.机号&#xff0c;不需…

Kernelized Correlation Filters KCF算法原理详解(阅读笔记)(待补充)

KCF 目录 KCF预备知识1. 岭回归2. 循环移位和循环矩阵3. 傅里叶对角化4. 方向梯度直方图&#xff08;HOG&#xff09; 正文1. 线性回归1.1. 岭回归1.2. 基于循环矩阵获取正负样本1.3. 基于傅里叶对角化的求解 2. 使用非线性回归对模型进行训练2.1. 应用kernel-trick的非线性模型…

如何使用IP代理解决亚马逊账号IP关联问题?

亚马逊账号IP关联问题是指当同一个IP地址下有多个亚马逊账号进行活动时&#xff0c;亚马逊会将它们关联在一起&#xff0c;从而可能导致账号被封禁或限制。 为了避免这种情况&#xff0c;许多人选择使用IP代理。 IP代理为什么可以解决亚马逊IP关联问题&#xff1f; IP代理是…

欲速则不达,慢就是快!

引言 随着生活水平的提高&#xff0c;不少人的目标从原先的解决温饱转变为追求内心充实&#xff0c;但由于现在的时间过得越来越快以及其他外部因素&#xff0c;我们对很多东西的获取越来越没耐心&#xff0c;例如书店经常会看到《7天精通Java》、《3天掌握XXX》等等之类的书籍…

金山下的wps,无法删除水印

RT&#xff0c;正常删除水印的流程是&#xff0c;插入-水印-删除水印。 如图的操作方法不生效时&#xff0c;可用下面的方法 点击页眉或页脚&#xff0c;进入页眉的编辑模式&#xff0c;可以看到水印变成可以选中的状态&#xff0c;选中&#xff0c;点击delete或者鼠标右键删…

如何使用Docker搭建YesPlayMusic网易云音乐播放器并发布至公网访问

文章目录 1. 安装Docker2. 本地安装部署YesPlayMusic3. 安装cpolar内网穿透4. 固定YesPlayMusic公网地址 本篇文章讲解如何使用Docker搭建YesPlayMusic网易云音乐播放器&#xff0c;并且结合cpolar内网穿透实现公网访问音乐播放器。 YesPlayMusic是一款优秀的个人音乐播放器&am…

知识蒸馏实战代码教学一(原理部分)

一、知识蒸馏的来源 知识蒸馏&#xff08;Knowledge Distillation&#xff09;源自于一篇由Hinton等人于2015年提出的论文《Distilling the Knowledge in a Neural Network》。这个方法旨在将一个大型、复杂的模型的知识&#xff08;通常称为教师模型&#xff09;转移到一个小型…

[Bug解决] Invalid bound statement (not found)出现原因和解决方法

1、问题描述 在写了一个很普通的查询语句之后&#xff0c;出现了下面的报错信息 org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): com.xxx.oauth.mapper.WxVisitorQrBeanMapper.selectByComIdAndEmpId at org.apache.ibatis.binding.Mappe…

嵌入式C语言学习——基于Linux与GCC(二)

系列文章目录 一.C语言常用关键字及运算符操作 文章目录 系列文章目录内存四区指针指针概述指针 修饰符constvolatiletypedef 指针运算符多级指针 数组数组空间字符空间及地址 结构体、共用体定义、字节对齐位域 内存分布图段错误分析 内存四区 C/C语言的内存四区&#xff0…

Django模板(四)

一、include标签 加载一个模板,并在当前上下文中进行渲染。这是一种在模板中 “包含” 其他模板的方式 简单的理解:在当前模板中引入另外一个模板内容 1.1、使用方法 模板名称可以是变量,也可以是单引号或双引号的硬编码(带引号)的字符串 {% include "foo/bar.ht…