Lesson 08 string类 (中)

C++:渴望力量吗,少年?

文章目录

  • 二、string类的介绍与使用
    • 2. 使用
        • (5)string类对象的修改操作
  • 三、拷贝
    • 1. 引入
    • 2. 浅拷贝
    • 3. 深拷贝
  • 总结


二、string类的介绍与使用

2. 使用

(5)string类对象的修改操作
函数名称功能说明
push_back在字符串后尾插字符
append在字符串后追加一个字符串
operator+= (重点)在字符串后追加字符串str
c_str(重点)返回C格式字符串
find + npos(重点)从字符串pos位置开始往后找字符c,返回该字符在字符串中的位置
rfind从字符串pos位置开始往前找字符c,返回该字符在字符串中的位置
substr在str中从pos位置开始,截取n个字符,然后将其返回

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

void test_string6()
{cout << "我是test_string6 :" << endl;string s;//s.reserve(100);//保留至少100个字节的空间,如果提前知道所需的空间,可以提前开好,因为扩容需要代价//容器的容量不一定就是我们开的那个,可能大于这个数字size_t old = s.capacity();//Return size of allocated storage(返回已分配的空间大小)cout << "初始" << s.capacity() << endl;for (size_t i = 0; i < 100; i++)//观察扩容的情况{s.push_back('x');if (s.capacity() != old){cout << "此时i = " << i << ", 扩容:" << s.capacity() << endl;old = s.capacity();}}s.reserve(10);//string可以自由地优化,并使字符串的容量大于 n。cout << s.capacity() << endl;
}void test_string7()//考虑现有的size和capacity的关系
{cout << "我是test_string7 :" << endl;string s1("hello world");cout << s1 << endl;cout << s1.size() << endl;//s.size() == s.length(),这两个都不包括斜杠零cout << s1.capacity() << endl;//s1.resize(13);//多出来的空间放置斜杠零//s1.resize(13, 'x');//已有数据个数小于resize的个数,相当于插入新的数据s1.resize(20, 'x');//如果resize开的空间大于最开始的capacity也就是15,就会自动扩容cout << s1 << endl;cout << s1.size() << endl;cout << s1.capacity() << endl;s1.resize(5);//已有数据的空间大于resize的空间,相当于删除数据cout << s1 << endl;cout << s1.size() << endl;cout << s1.capacity() << endl;string s2;s2.resize(10, '#');//字符串没有数据/没有初始化,相当于直接填充数据cout << s2 << endl;cout << s2.size() << endl;cout << s2.capacity() << endl;s2[0]++;s2.at(0)++;//Return value:The character at the specified position in the string.(返回特定位置的字符)cout << s2 << endl;
}void test_string8()
{cout << "我是test_string8 :" << endl;string ss("world");string s;s.push_back('#');s.append("hello");//在对象s的结尾追加,和pushback、+=的效果差不多,一般使用+=多一些s.append(ss);cout << s << endl;s += '#';s += "hello";s += ss;cout << s << endl;string ret1 = ss + '#';//尽量使用 +=,因为 + 的拷贝构造次数会更多,影响效率string ret2 = ss + "hello";cout << ret1 << endl;cout << ret2 << endl;
}void test_string9()
{cout << "我是test_string9 :" << endl;std::string str("xxxxxxx");std::string base = "The quick brown fox jumps over a lazy dog.";//str = base;//可以直接用 = 赋值//cout << str << endl;str.assign(base);//相当于base赋值给str,会覆盖原来的值std::cout << str << '\n';str.assign(base, 5, 10);//从base下标为5的位置开始将10个字符赋值给strstd::cout << str << '\n';//str.assign(base.begin()+16,base.end()-12);//参数也可以是迭代器
}void test_string10()
{cout << "我是test_string10 :" << endl;// insert/erase/repalce能不用就尽量不用,因为他们都涉及挪动数据,效率不高// 接口设计复杂繁多,需要时查一下文档即可std::string str("hello world");str.insert(0, 1, 'x');//在下标为第一个参数的位置插入个数为第二个参数的第三个参数str.insert(str.begin(), 'x');cout << str << endl;str.erase(5);//从下标为5的位置开始擦除内容,第二个参数是缺省参数,不写默认擦除第一个参数后面的所有内容cout << str << endl;std::string s1("hello world");s1.replace(5, 3, "%%20");//将从指定位置开始的指定个数字符替换为指定字符(串)//3:Number of characters to replace (if the string is shorter, as many characters as possible are replaced).cout << s1 << endl;// 要求将空格替换为20%(以空间换时间)(replace效率不够高)std::string s2("The quick brown fox jumps over a lazy dog.");string s3;for (auto ch : s2){if (ch != ' '){s3 += ch;}else{s3 += "20%";}}//s2 = s3;//s2.assign(s3);printf("s2:%p\n", s2.c_str());//c_str可以返回这个对象的指针printf("s3:%p\n", s3.c_str());//交换的目的是让s2的内容变成修改之后的内容swap(s2, s3);//注意有swap模板库,也有全局函数swap,还有string自己提供的swap,如果用的话一般自定义类型不要用模板的swap,因为要拷贝构造的次数比较多//不过一般直接调用swap交换字符串也不会调用模板库的,因为匹配的模板和匹配的已经实现的函数之间编译器会优先使用已经实现的函数//s2.swap(s3);printf("s2:%p\n", s2.c_str());printf("s3:%p\n", s3.c_str());cout << s2 << endl;
}void test_string11()
{cout << "我是test_string11 :" << endl;string s1("test.cpp.tar.zip");//返回找到的下标//size_t i = s1.find('.');//正向查找第一个 . size_t i = s1.rfind('.');//反向查找第一个 .cout << i << endl;string s2 = s1.substr(i, 3);//从下标为i的位置开始取子串,第二个参数没写就取剩下的全部cout << s2 << endl;//string s3("https://legacy.cplusplus.com/reference/string/string/rfind/");string s3("ftp://www.baidu.com/?tn=65081411_1_oem_dg");// 协议// 域名// 资源名string sub1, sub2, sub3;size_t i1 = s3.find(':');if (i1 != string::npos)//因为找不到对应的字符是返回npossub1 = s3.substr(0, i1);//注意是左闭右开的区间,substr返回一个子串elsecout << "没有找到i1" << endl;size_t i2 = s3.find('/', i1 + 3);if (i2 != string::npos)sub2 = s3.substr(i1 + 3, i2 - (i1 + 3));elsecout << "没有找到i2" << endl;sub3 = s3.substr(i2 + 1);//取到末尾cout << sub1 << endl;cout << sub2 << endl;cout << sub3 << endl;
}void test_string12()
{cout << "我是test_string12 :" << endl;/*std::string str("Please, replace the vowels in this sentence by asterisks.");std::size_t found = str.find_first_not_of("abc");//找到字符串第一个不是abc的字符并返回下标while (found != std::string::npos){str[found] = '*';found = str.find_first_not_of("abcdefg", found + 1);//第二个参数:Position of the first character in the string to be considered in the search.}std::cout << str << '\n';*/std::string str("Please, replace the vowels in this sentence by asterisks.");std::size_t found = str.find_first_of("abcd");//找到第一个是abcd中其中一个字符的并返回下标while (found != std::string::npos){str[found] = '*';found = str.find_first_of("abcd", found + 1);}std::cout << str << '\n';}int main()
{test_string6();test_string7();test_string8();test_string9();test_string10();test_string11();test_string12();return 0;
}

  string类中还有一些其他的操作,这里不一一列举,大家在需要用到时查文档即可。

三、拷贝

1. 引入

  上面已经对string类进行了简单的介绍,其他不太常用的函数就不再写了,只要能够保证上面的内容都能熟练运用即可。为什么模拟实现string类?模拟string类最主要是实现string类的构造、拷贝构造、赋值运算符重载以及析构函数,只有能够模拟出来,才是真正了解它的底层逻辑。
  问题:以下string类的实现是否有错?
代码如下:

class String {
public:String(const char* str = ""){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);
}

  这段代码其实是有很大的问题的,这个关于拷贝的问题也是我们学习C++经常会遇到的问题,所以还是得理解为什么。
在这里插入图片描述
  上述String类没有显式定义其拷贝构造函数与赋值运算符重载,此时编译器会合成默认的,当用s1构造s2时,编译器会调用默认的拷贝构造。最终导致的问题是,s1、s2共用同一块内存空间,在释放时同一块空间被释放多次而引起程序崩溃,这种拷贝方式,称为浅拷贝。

2. 浅拷贝

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

3. 深拷贝

  如果一个类中涉及到资源的管理,其拷贝构造函数、赋值运算符重载以及析构函数必须要显式给出。一般情况都是按照深拷贝方式提供。
  上面的代码可以采用深拷贝解决浅拷贝问题,即:每个对象都有一份独立的资源,不和其他对象共享。
在这里插入图片描述
  如图,显式地定义拷贝构造函数,在初始化列表重新为_pStr开辟一个新的空间,再把数据从就空间拷贝过去,这样就实现了深拷贝。


总结

  前面这两小节主要还是为了下一节地模拟实现做准备,要尽可能做到理解并熟练运用。

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

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

相关文章

2023年下半年计算机等级考试—信息安全三级部分真题

1.前言 刚参加完2023年下半年计算机等级考试—信息安全三级。笔者凭借记忆将考到的题进行如下汇总,并整理正确答案。仅供各位参考! 2.题型及分值 上机考试,考试时长120分钟,满分100分。 选择题 60分 50道题,每道题1.2分 填空题 20分 20道题 每道题1分 综合应用题 2…

Scrum敏捷开发流程及支撑工具

Scrum是一种敏捷开发框架&#xff0c;用于管理复杂的项目。以下这些步骤构成了Scrum敏捷开发流程的核心。通过不断迭代、灵活应对变化和持续反馈&#xff0c;Scrum框架帮助团队快速交付高质量的产品。 以下是Scrum敏捷开发流程的基本步骤&#xff1a; 产品Backlog创建&#xf…

基于协同过滤算法的美食推荐系统研究与实现

点我完整下载&#xff1a;基于协同过滤算法的美食推荐系统研究与实现 基于协同过滤算法的美食推荐系统研究与实现 "Research and Implementation of a Food Recommendation System based on Collaborative Filtering Algorithm" 目录 目录 2 摘要 3 关键词 3 第一章 …

Windows系统Powershell自带的Test-NetConnection命令测试网络情况

Test-Connection it-000571,192.168.20.205 //测试ip连通性&#xff0c;类似ping&#xff0c;用,号可以同时测试多个IP Test-NetConnection -Computername it-000571 -traceRoute //追踪域名it-000571的路由 Test-NetConnection 192.168.75.216 -port 3389 //…

微服务--06--Sentinel 限流、熔断

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 1.微服务保护雪崩问题服务保护方案1.1.请求限流1.2.线程隔离1.3.服务熔断 2.Sentinel2.1.介绍和安装官方网站&#xff1a;[https://sentinelguard.io/zh-cn/](https…

打造高效项目团队,离不开有效的反馈机制

为了确保项目高效交付&#xff0c;项目经理需要在管理过程中及时发现问题并解决&#xff0c;所以80%的时间都在进行沟通以及各种项目汇报。但项目经理往往会陷入低频沟通、无意义汇报的困局&#xff0c;进而导致四处救火、项目各种延误、团队的工作效率低下。例如&#xff1a; …

Leetcode2336 无限集中的最小数字

题目&#xff1a; 现有一个包含所有正整数的集合 [1, 2, 3, 4, 5, ...] 。 实现 SmallestInfiniteSet 类&#xff1a; SmallestInfiniteSet() 初始化 SmallestInfiniteSet 对象以包含 所有 正整数。int popSmallest() 移除 并返回该无限集中的最小整数。void addBack(int nu…

VERAS:AI驱动的Revit可视化渲染插件

Veras 是一款基于生成式AI 的可视化工具&#xff0c;可以使用自然语言生成3D渲染效果&#xff0c;兼容Revit、Rhino 和 SketchUp。Veras for Revit工具使用 Revit 模型内部的 3D 视图。 NSDT工具推荐&#xff1a; Three.js AI纹理开发包 - YOLO合成数据生成器 - GLTF/GLB在线编…

ES6模板字符串的基本使用

ES6新增了模板字符串&#xff0c;让我们拼接字符串时更方便 注意:切记使用反引号作为字符串的定界符分隔的字面量 1.拼接 在我们模板字符串出现之前&#xff0c;我们想要拼接字符串是比较麻烦的 const name "杰克";const age 18;// 以前的拼接字符串console.log(…

如何把ipa文件(iOS安装包)安装到iPhone手机上? 附方法汇总

文章目录 概要整体架构流程技术名词解释技术细节小结 概要 技术细节 目录 Appuploader 常见错误及解决方法 苹果APP安装包ipa如何安装在手机上&#xff1f;很多人不知道怎么把ipa文件安装到手机上&#xff0c;这里就整理了苹果APP安装到iOS设备上的方式&#xff0c;仅供参考 苹…

说说你对slot的理解?slot使用场景有哪些?

面试官&#xff1a;说说你对slot的理解&#xff1f;slot使用场景有哪些&#xff1f; 一、slot是什么 在HTML中 slot 元素 &#xff0c;作为 Web Components 技术套件的一部分&#xff0c;是Web组件内的一个占位符 该占位符可以在后期使用自己的标记语言填充 举个栗子 <t…

安科瑞智能照明系统在福建二建大厦项目上的应用

【摘要】&#xff1a;智能化已经成为当今建筑发展的主流技术、涵盖从空调系统、消防系统到安全防范系统以及完善的计算机网络和通信系统。但是长期以来、智能照明在国内一直被忽视、大多数建筑物仍然沿用传统的照明控制方式、部分智能大厦采用楼宇自控&#xff08;BA&#xff0…

pm2部署vue项目,Vue项目的部署在服务器

这是一篇介绍pm2简单实用的文章&#xff0c; 以启动vue项目为例&#xff0c;动态部署Vue项目&#xff0c;部署后便可直接访问服务器的Vue项目 1.安装pm2 npm install pm2 -g2.启动Vue项目 进入vue项目的目录&#xff0c;创建一个js文件&#xff0c; # 在vue项目下创建一个j…

vue2全局混入正确使用场景和错误场景示例

全局混入在 Vue.js 中的使用场景需要谨慎考虑&#xff0c;因为它会影响所有组件。以下是一些正确和错误的使用场景的例子&#xff1a; 正确的使用场景&#xff1a; 全局工具方法&#xff1a; // 正确的使用场景 Vue.mixin({methods: {$formatDate: function (date) {// 格式化…

如何使用 RestTemplate 进行 Spring Boot 微服务通信示例?

在 Spring Boot 微服务架构中&#xff0c;RestTemplate 是一个强大的工具&#xff0c;用于简化微服务之间的通信。下面是一个简单的示例&#xff0c;演示如何使用 RestTemplate 进行微服务之间的 HTTP 通信。 首先&#xff0c;确保你的 Spring Boot 项目中已经添加了 spring-b…

项目问题总结

加油&#xff01; 文章目录 1. 二次封装 axios 做了什么2. 路由的生命周期3、 vue2 和 vue3的区别4、vuex 1. 二次封装 axios 做了什么 请求拦截 成功&#xff1a; 头部添加token失败&#xff1a; 返回错误信息 响应拦截 如果没有 token &#xff0c;就提示转为登录页 路由守…

算法面试题--树与对象数组的转化

1. Array -> Tree var arr [{ id: 12, parentId: 1, name: "朝阳区" },{ id: 241, parentId: 24, name: "田林街道" },{ id: 31, parentId: 3, name: "广州市" },{ id: 13, parentId: 1, name: "昌平区" },{ id: 2421, parentId:…

曲面拼接oled屏幕为何受到企业展览青睐

曲面拼接OLED屏幕受到企业展览青睐的原因主要有以下几点&#xff1a; 创新的技术&#xff1a;曲面拼接OLED屏幕采用先进的OLED技术&#xff0c;具有自发光原理&#xff0c;可以实现真正的黑色和高对比度&#xff0c;呈现出生动的图像。其每个像素都能独立发光&#xff0c;没有背…

Windows系统下使用PHPCS+PHPMD+GIT钩子

前言 使用PHPCSGIT钩子保障团队开发中代码风格一致性实践 使用PHPMD提高代码质量与可读性 0.介绍 PHP_CodeSniffer php代码嗅探器 包含phpcs(php code standard 代码标准) phpcbf(php code beautify fix 代码美化修复) 是一个代码风格检测工具,着重代码规范 它包含两类脚本…

Android Sensor调用从上层到底层

Sensor应用层调用 SensorManager mSensorManager; Sensor mSensor; mSensorManager (SensorManager) getSystemService(SENSOR_SERVICE); //获取sensor服务 mSensor mSensorManager.getDefaultSensor(Sensor.TYPE_PRESSURE); //获取默认sensor类型mSensorManager.registerLi…