当前位置: 首页 > news >正文

从零到精通:用C++ STL string优化代码

目录

1:为什么要学习string类

2:标准库中的string类

2.1:string类(了解)

2.2:总结

3:string类的常用接口

3.1:string类对象的常见构造

3.1.1:代码1

3.1.2:代码2

3.2:string类对象的遍历操作

3.2.1:代码1(begin + end)

3.2.2:代码2(rbegin + rend)

3.3:string类对象的容量遍历

3.3.1:代码1(测试容量)

3.3.2:代码2(测试resize)

3.3.3:代码3(测试reserve)

3.4:string对象的访问

3.5:string类对象的修改操作

3.5.1:代码1

3.5.2:代码2

3.5.3:代码3

3.6:string类的非成员函数

4:vs下与g++下string结构的说明

4.1:vs下string的结构

4.2:g++下的string

hello,家人们,今天咱们来介绍string相关的操作,好啦,废话不多讲,开干.


1:为什么要学习string类

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

2:标准库中的string

2.1:string类(了解)

  1. 字符串时表示字符序列的类.
  2. 标准的字符串提供了对此类对象的支持,其接口类似于字符容器的接口,但添加了专门用于操作单字节字符字符串的设计特性.
  3. string类是使用char(即作为它的字符类型,使用它的默认char_traits和分配器类型(关于模板的更多信息,可以去阅读basic_string)
  4. string类是basic_string模板类的一个实例,它使用char来实例化basic_string模板类,并用char_traits和allocator作为basic_string的默认参数(根于更多的模板信息可以参考basic_string)
PS:注意,这个类独立于所使用的编码来处理字节:如果用来处理多字节或变长字符(如UTF-8)的序列,这个类的所有成员(如长度或大小)以及它的迭代器,将仍然按照字节(而不是实际编码的字符)来操作~

2.2:总结

1. string是表示字符串的字符串类
2. 该类的接口与常规容器的接口基本相同,再添加了一些专门用来操作string的常规操作。
3. string在底层实际是:basic_string模板类的别名,typedef basic_string<char,char_traits, allocator>string;
4. 不能操作多字节或者变长字符的序列。

3:string类的常用接口

3.1:string类对象的常见构造

3.1.1:代码1

#define  _CRT_SECURE_NO_WARNINGS
#include <iostream> 
using namespace std;
#include <string>void test_constructor()
{//构造空的字符串对象即空字符串string s1;//使用字符串构造字符串对象string s2("hello world");//拷贝构造,将s2拷贝给s3string s3(s2);//拷贝字符串,并且只拷贝5个字符string s4("hello world", 5);cout << "s1" << s1 << endl;cout << "s2 = " << s2 << endl;cout << "s3 = " << s3 << endl;cout << "s4 = " << s4 << endl;
}int main()
{test_constructor();return 0;
}

3.1.2:代码2

#define  _CRT_SECURE_NO_WARNINGS
#include <iostream> 
using namespace std;
#include <string>void test_constructor()
{//从下标为3的位置开始拷贝字符串,拷贝12个字符串string s5("you are welcome", 3, 12);//使用字符'*'填充对象s6,填充10个string s6(10, '#');string s7;//赋值运算符重载s7 = s5;cout << "s5 = " << s5 << endl;cout << "s6 = " << s6 << endl;cout << "s7 = " << s7 << endl;
}int main()
{test_constructor();return 0;
}

3.2:string类对象的遍历操作

3.2.1:代码1(begin + end)

#define  _CRT_SECURE_NO_WARNINGS
#include <iostream> 
using namespace std;
#include <string>void test_string_iterators()
{string str("how are you");//获取指向第一个字符的迭代器std::string::iterator it = str.begin();while(it != str.end()){cout << *it;it++;}
}int main()
{test_string_iterators();return 0;
}

3.2.2:代码2(rbegin + rend)

#define  _CRT_SECURE_NO_WARNINGS
#include <iostream> 
using namespace std;
#include <string>void test_string_reverse_iterators()
{string str("how are you");//使用反向迭代器时需要指定类域string::reverse_iterator rit = str.rbegin();string::reverse_iterator ren = str.rend();while(rit != str.rend()){cout << *rit;++rit;}
}int main()
{test_string_reverse_iterators();return 0;
}

3.3:string类对象的容量遍历

3.3.1:代码1(测试容量)

#define  _CRT_SECURE_NO_WARNINGS
#include <iostream> 
using namespace std;
#include <string>void test_string_capacity()
{string str("hello world");//返回字符串的长度cout << "size:>" << str.size() << endl;cout << "length:>" << str.length() << endl;//返回字符串所能触及的最大长度cout << "max_size:>" << str.max_size() << endl;//返回当前对象所分配的容量大小cout << "capacity:>" << str.capacity() << endl;//清空字符串但是不影响容量str.clear();cout << "size:>" << str.size() << endl;cout << "capacity:>" << str.capacity() << endl;//判断字符串是否为空str = "hello world";int result = str.empty();cout <<"清空前:>" << result << endl;str.clear();cout <<"清空后:>" << str.empty() << endl;//默认将capacity缩到15str.shrink_to_fit();cout << "size:>" << str.size() << endl;cout << "capacity:>" << str.capacity() << endl;
}int main()
{test_string_capacity();return 0;
}

3.3.2:代码2(测试resize)

#define  _CRT_SECURE_NO_WARNINGS
#include <iostream> 
using namespace std;
#include <string>void test_string_resize()
{string str("hello world");//比size小则进行删除str.resize(10);cout << "size:>" << str.size() << endl;cout << "capacity:>" << str.capacity() << endl;cout << str << endl;cout << endl;//比size大但小于capacity会用改变size,并用\0插入str.resize(13);cout << "size:>" << str.size() << endl;cout << "capacity:>" << str.capacity() << endl;cout << str << endl;//比capacity大,会先改变size的大小同时进行扩容str.resize(20);cout << "size:>" << str.size() << endl;cout << "capacity:>" << str.capacity() << endl;cout << str << endl;
}int main()
{test_string_resize();return 0;
}

3.3.3:代码3(测试reserve)

#define  _CRT_SECURE_NO_WARNINGS
#include <iostream> 
using namespace std;
#include <string>void test_string_reserve()
{string str("hello world");cout << "size:>" << str.size() << endl;cout << "capacity:>" << str.capacity() << endl;cout << "reserver后" << endl;cout << endl;//比size小不变化str.reserve(10);cout << "size:>" << str.size() << endl;cout << "capacity:>" << str.capacity() << endl;cout << str << endl;cout << endl;//比size大但小于capacity也不发生变化str.reserve(13);cout << "size:>" << str.size() << endl;cout << "capacity:>" << str.capacity() << endl;cout << str << endl;cout << endl;//比capacity大才会进行扩容str.reserve(20);cout << "size:>" << str.size() << endl;cout << "capacity:>" << str.capacity() << endl;cout << str << endl;
}int main()
{test_string_reserve();return 0;
}

  • clear只是将string中的有效字符清空,不改变底层的空间大小.
  • resize(size_t n)与resize(size_n,char c)都是将字符串中的有效字符个数改变到n个,不同的是,当字符个数增多时:resize(n)0来填充多出的元素空间,resize(size_n,char c)用字符c来填充多出的空间.
  • reserve(size res_arg):为string预留空间,不改变有效元素,只有在reserve的参数大于底层的空间总大小时 reserve才会进行扩容.

3.4:string对象的访问

#define  _CRT_SECURE_NO_WARNINGS
#include <iostream> 
using namespace std;
#include <string>void test_string_element_access()
{string s1("hello world");for(size_t i = 0; i < s1.size(); i++){cout << s1[i] << " ";}cout << endl;for (size_t i = 0; i < s1.size(); i++){cout << s1.operator[](i) << " ";}cout << endl;//获取尾部元素cout << s1.back() << endl;//获取头部元素cout << s1.front() << endl;cout << s1.at(0) << endl;
}int main()
{test_string_element_access();return 0;
}

3.5:string类对象的修改操作

3.5.1:代码1
 

#define  _CRT_SECURE_NO_WARNINGS
#include <iostream> 
using namespace std;
#include <string>void test_string_Modifiers()
{string s1("hello world");string s2("bit");//operator+=运算符重载s1 += s2;s1 += 'c';s1 += "bit";cout << s1 << endl;cout << endl;//appends1.append(" hello world");cout << s1 << endl;//给对象s1分配新内容,并且代替当初的字符串内容s1.assign(" xxxxxx");cout << s1 << endl;
}int main()
{test_string_Modifiers();return 0;
}

3.5.2:代码2

#define  _CRT_SECURE_NO_WARNINGS
#include <iostream> 
using namespace std;
#include <string>void test_string_Modifiers()
{string s1("hello world");string s2("bit");//在下标为5的位置插入字符串0s1.insert(5, "0");cout << s1 << endl;cout << endl;//从下标为5的位置开始抹除,抹除的长度为3s1.erase(5, 3);cout << s1 << endl;cout << endl;//交换两个字符串的内容s1.swap(s2);cout<<"s1 == " << s1 << endl;cout<<"s2 == " << s2 << endl;
}int main()
{test_string_Modifiers();return 0;
}

3.5.3:代码3

#define  _CRT_SECURE_NO_WARNINGS
#include <iostream> 
using namespace std;
#include <string>void test_string_operatorions()
{string s1("hello world");string s2("bit");//返回C类型的字符串cout << s1.c_str() << endl;cout << s2.c_str() << endl;//find//查找字符,默认从首元素开始cout << s1.find(' ') << endl;//查找字符,从下标为5的位置开始cout << s1.find(' ', 5) << endl;//查找字符串,返回出现该字符串的首字符位置,类似于strstrcout << s1.find("world") << endl;cout << endl;//rind//查找最后一次出现该字符的位置cout << s1.rfind('l') << endl;//查找最后一次出现该字符串的位置cout << s1.rfind("wo") << endl;cout << endl;size_t position = s1.find(' ');//从position + 1的位置开始取后面字符串cout << s1.substr(position + 1);
}int main()
{test_string_operatorions();return 0;
}

3.6:string类的非成员函数

#define  _CRT_SECURE_NO_WARNINGS
#include <iostream> 
using namespace std;
#include <string>void test_string_Non_member_function_overloads()
{string s1("hello world");string s2("hello world");string s3("hello xorld");cout << (s1 == s2) << endl;cout << (s1 > s2) << endl;cout << endl;//读取一行字符串getline(cin, s1);string::iterator it = s1.begin();string::iterator end = s1.end();cout << s1 << endl;cout << endl;//区间为左闭右开,反转字符串reverse(it, end);cout << s1 << endl;
}int main()
{test_string_Non_member_function_overloads();return 0;
}

4:vs下与g++下string结构的说明

PS:这是在32位平台下进行验证滴,32位平台下,指针占4个字节

4.1: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;
  1. 这种设计也是有一定道理的,大多数情况下字符串的长度都小于16,那string对象创建好之后,内部已经有了16个字符数组的固定空间,不需要通过堆创建,效率高.
  2. 还有一个size_t字段保存字符串长度,一个size_t字段保存从堆上开辟空间总的容量.
  3. 有一个指针 做一些其他事情.
    因此总共占 16 + 4 + 4 + 4 = 28个字节.

 

4.2:g++下的string

g++下,string是通过写时拷贝实现的,string对象总共占4个字节,内部只包含了一个指针,该指针将来指向一块堆空间,内部包含了如下字段:
        
  1. 空间总大小.
  2. 字符串有效长度.
  3. 引用计数.
  4. 指向堆空间的指针,用来存储字符串
struct _Rep_base
{size_type _M_length;size_type _M_capacity;_Atomic_word _M_refcount;
};

 好啦,uu们,string的这部分滴详细内容博主就讲到这里啦,如果uu们觉得博主讲的不错的话,请动动你们滴小手给博主点点赞,你们滴鼓励将成为博主源源不断滴动力,同时也欢迎大家来指正博主滴错误~

相关文章:

从零到精通:用C++ STL string优化代码

目录 1:为什么要学习string类 2:标准库中的string类 2.1:string类(了解) 2.2:总结 3:string类的常用接口 3.1:string类对象的常见构造 3.1.1:代码1 3.1.2:代码2 3.2:string类对象的遍历操作 3.2.1:代码1(begin end) 3.2.2:代码2(rbegin rend) 3.3:string类对象的…...

鸿蒙轻内核M核源码分析系列五 时间管理

往期知识点记录&#xff1a; 鸿蒙&#xff08;HarmonyOS&#xff09;应用层开发&#xff08;北向&#xff09;知识点汇总 持续更新中…… 在鸿蒙轻内核源码分析上一篇文章中&#xff0c;我们剖析了中断的源码&#xff0c;简单提到了Tick中断。本文会继续分析Tick和时间相关的源…...

Python Opencv鼠标回调

使用 OpenCV 的 cv2.setMouseCallback() 方法来捕捉鼠标事件&#xff0c;并实现以下功能&#xff1a; 实时在鼠标指针附近显示其位置的像素坐标。通过左键双击&#xff0c;将像素坐标记录到数组中。通过右键点击&#xff0c;取消上一次添加的坐标。 下面是实现代码的示例&…...

Ubuntu环境的MySql下载安装

下载压缩包 此文章下载的mysql版本位5.7.29 sudo wget https://downloads.mysql.com/archives/get/p/23/file/mysql-server_5.7.29-1ubuntu18.04_amd64.deb-bundle.tar解压缩 sudo tar -xvf mysql-server_5.7.29-1ubuntu18.04_amd64.deb-bundle.tar命令解释 -x&#xff1a;…...

Android系统去掉WIFI模块

先说应用场景&#xff0c;有些特定设备&#xff0c;不能连接wifi。需要隐藏的模块&#xff0c;QS面板模块的wifi,还有设置里面的wifi.由于QS属于SystemUI&#xff0c;熟悉SystemUI之后&#xff0c;就可以直接去SystemUi那里找&#xff0c;找到QSTitle 默认配置的地方。 一、…...

代码随想录 -- 二叉树 -- 翻转二叉树

226. 翻转二叉树 - 力扣&#xff08;LeetCode&#xff09; 递归比较简单 class Solution(object):def invertTree(self, root):if rootNone:returnnode rootif node.left or node.right:tempnode.leftnode.leftnode.rightnode.righttempself.invertTree(node.left)self.inve…...

Node.js之文件复制

1.方式一&#xff1a;readFile // 导入fs模块 const fs require("fs") // 导入process模块 const process require("process")// 读取文件内容 let data fs.writeFileSync(./test.txt) // 写入文件内容 fs.writeFileSync(./test1.txt, data) 2.方式二&…...

新手c语言讲解及题目分享(十六)--文件系统专项练习

在我刚开始学习c语言的时候就跳过了这一章节&#xff0c;但在后面慢慢发现这一章节还是比较重要的,如果你报考了计算机二级c语言的话&#xff0c;你应该可以看到后面的三个大题有时会涉及到这章。所以说这章还是非常重要的。 目录 前言 一.打开文件 1.Fopen( )函数返回值 2&…...

RabbitMQ本地Ubuntu系统环境部署与无公网IP远程连接服务端实战演示

文章目录 前言1.安装erlang 语言2.安装rabbitMQ3. 安装内网穿透工具3.1 安装cpolar内网穿透3.2 创建HTTP隧道 4. 公网远程连接5.固定公网TCP地址5.1 保留一个固定的公网TCP端口地址5.2 配置固定公网TCP端口地址 &#x1f4a1; 推荐 前些天发现了一个巨牛的人工智能学习网站&am…...

[C++#28][多态] 两个条件 | 虚函数表 | 抽象类 | override 和 final | 重载 重写 重定义

目录 0.引入 1.虚函数 1. 虚函数的重写/覆盖 2. 特例1&#xff1a;不加 virtual 关键字的重写 3. 特例2&#xff1a;协变&#xff08;了解&#xff09; 2.多态的构成和细节 1. C11 的 override 和 final 1. final 不可重写 2. override 报错检查 ⭕2. 重载、覆盖&…...

List 集合指定值升序降序排列Comparator实现

升序排序 升序排序通常是指从小到大的排序。对于数值类型来说&#xff0c;可以直接使用 compareTo 方法&#xff0c;而对于其他类型&#xff0c;可以根据实际需求实现比较逻辑。 示例代码 import java.util.Comparator; import java.util.List; import java.util.ArrayList;cl…...

【Day07】

目录 MySQL-DQL- 基本查询 MySQL-DQL- 条件查询 MySQL-DQL- 聚合函数 MySQL-DQL- 分组查询 MySQL-DQL- 排序查询 MySQL-DQL- 分页查询 MySQL-DQL- 案例 MySQL-多表设计-一对多 MySQL-多表设计-一对多-外键约束 MySQL-多表设计-一对一&多对多 MySQL-多表设计-案例…...

shell 控制台显示彩色文字的方法

在shell脚本中,如果我们希望在控制台能显示带颜色的文字, 那就需要使用shell中的色彩专用变量代码来进行. shell中的各种颜色代码定义 # 颜色定义 BLACK"\033[0;30m" DARK_GRAY"\033[1;30m" BLUE"\033[0;34m" LIGHT_BLUE"\033[1;3…...

Nginx: 缓存, 不缓存特定内容和缓存失效降低上游压力策略及其配置示例

概述 在负载均衡的过程中&#xff0c;有一个比较重要的概念&#xff0c;就是缓存利用缓存可以很好协调Nginx在客户端和上游服务器之间的速度不匹配的矛盾从而很好的解决整体系统的响应速度 如果用户需要通过Nginx获取某一些内容的时候&#xff0c;发起一个request请求这个请求…...

Python 全栈系列266 Kafka服务的Docker搭建

说明 在大量数据处理任务下的缓存与分发 这个算是来自顾同学的助攻1&#xff0c;我有点java绝缘体的体质&#xff0c;碰到和java相关的安装部署总会碰到点奇怪的问题&#xff0c;不过现在已经搞定了。测试也接近了kafka官方标称的性能。考虑到网络、消息的大小等因素&#xff0…...

集合框架,List常用API,栈和队列初识

回顾 集合框架 两个重点——ArrayList和HashSet. Vector/ArraysList/LinkedList区别 VectorArraysListLinkedList底层实现数组数组链表线程安全安全不安全不安全增删效率较低较低高扩容*2*1.5-------- &#xff08;>>&#xff09;运算级最低&#xff0c;记得加括号。 常…...

构建全景式智慧文旅生态:EasyCVR视频汇聚平台与AR/VR技术的深度融合实践

在科技日新月异的今天&#xff0c;AR&#xff08;增强现实&#xff09;和VR&#xff08;虚拟现实&#xff09;技术正以前所未有的速度改变着我们的生活方式和工作模式。而EasyCVR视频汇聚平台&#xff0c;作为一款基于云-边-端一体化架构的视频融合AI智能分析平台&#xff0c;可…...

C++结构体声明时初始化

提示&#xff1a;文章 文章目录 前言一、背景二、 2.1 2.2 总结 前言 前期疑问&#xff1a; 本文目标&#xff1a; 一、背景 最近 二、 2.1 c 结构体默认初始化 在C中&#xff0c;结构体的默认成员初始化可以通过构造函数来完成。如果没有为结构体提供构造函数&#x…...

基于微信的热门景点推荐小程序的设计与实现(论文+源码)_kaic

摘 要 近些年来互联网迅速发展人们生活水平也稳步提升&#xff0c;人们也越来越热衷于旅游来提高生活品质。互联网的应用与发展也使得人们获取旅游信息的方法也更加丰富&#xff0c;以前的景点推荐系统现在已经不足以满足用户的要求了&#xff0c;也不能满足不同用户自身的个…...

9、设计模式

设计模式 1、工厂模式 在工厂模式中&#xff0c;我们在创建对象时不会对客户端暴露创建逻辑&#xff0c;并且是通过使用一个共同的接口来指向新创建的对象。工厂模式作为一种创建模式&#xff0c;一般在创建复杂对象时&#xff0c;考虑使用&#xff1b;在创建简单对象时&…...

conda相比python好处

Conda 作为 Python 的环境和包管理工具&#xff0c;相比原生 Python 生态&#xff08;如 pip 虚拟环境&#xff09;有许多独特优势&#xff0c;尤其在多项目管理、依赖处理和跨平台兼容性等方面表现更优。以下是 Conda 的核心好处&#xff1a; 一、一站式环境管理&#xff1a…...

<6>-MySQL表的增删查改

目录 一&#xff0c;create&#xff08;创建表&#xff09; 二&#xff0c;retrieve&#xff08;查询表&#xff09; 1&#xff0c;select列 2&#xff0c;where条件 三&#xff0c;update&#xff08;更新表&#xff09; 四&#xff0c;delete&#xff08;删除表&#xf…...

云计算——弹性云计算器(ECS)

弹性云服务器&#xff1a;ECS 概述 云计算重构了ICT系统&#xff0c;云计算平台厂商推出使得厂家能够主要关注应用管理而非平台管理的云平台&#xff0c;包含如下主要概念。 ECS&#xff08;Elastic Cloud Server&#xff09;&#xff1a;即弹性云服务器&#xff0c;是云计算…...

C++:std::is_convertible

C++标志库中提供is_convertible,可以测试一种类型是否可以转换为另一只类型: template <class From, class To> struct is_convertible; 使用举例: #include <iostream> #include <string>using namespace std;struct A { }; struct B : A { };int main…...

React Native 导航系统实战(React Navigation)

导航系统实战&#xff08;React Navigation&#xff09; React Navigation 是 React Native 应用中最常用的导航库之一&#xff0c;它提供了多种导航模式&#xff0c;如堆栈导航&#xff08;Stack Navigator&#xff09;、标签导航&#xff08;Tab Navigator&#xff09;和抽屉…...

Mybatis逆向工程,动态创建实体类、条件扩展类、Mapper接口、Mapper.xml映射文件

今天呢&#xff0c;博主的学习进度也是步入了Java Mybatis 框架&#xff0c;目前正在逐步杨帆旗航。 那么接下来就给大家出一期有关 Mybatis 逆向工程的教学&#xff0c;希望能对大家有所帮助&#xff0c;也特别欢迎大家指点不足之处&#xff0c;小生很乐意接受正确的建议&…...

三体问题详解

从物理学角度&#xff0c;三体问题之所以不稳定&#xff0c;是因为三个天体在万有引力作用下相互作用&#xff0c;形成一个非线性耦合系统。我们可以从牛顿经典力学出发&#xff0c;列出具体的运动方程&#xff0c;并说明为何这个系统本质上是混沌的&#xff0c;无法得到一般解…...

工业自动化时代的精准装配革新:迁移科技3D视觉系统如何重塑机器人定位装配

AI3D视觉的工业赋能者 迁移科技成立于2017年&#xff0c;作为行业领先的3D工业相机及视觉系统供应商&#xff0c;累计完成数亿元融资。其核心技术覆盖硬件设计、算法优化及软件集成&#xff0c;通过稳定、易用、高回报的AI3D视觉系统&#xff0c;为汽车、新能源、金属制造等行…...

laravel8+vue3.0+element-plus搭建方法

创建 laravel8 项目 composer create-project --prefer-dist laravel/laravel laravel8 8.* 安装 laravel/ui composer require laravel/ui 修改 package.json 文件 "devDependencies": {"vue/compiler-sfc": "^3.0.7","axios": …...

push [特殊字符] present

push &#x1f19a; present 前言present和dismiss特点代码演示 push和pop特点代码演示 前言 在 iOS 开发中&#xff0c;push 和 present 是两种不同的视图控制器切换方式&#xff0c;它们有着显著的区别。 present和dismiss 特点 在当前控制器上方新建视图层级需要手动调用…...