当前位置: 首页 > 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们觉得博主讲的不错的话,请动动你们滴小手给博主点点赞,你们滴鼓励将成为博主源源不断滴动力,同时也欢迎大家来指正博主滴错误~

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • Biome-BGC生态系统模型与Python融合技术实践应用
  • 记一次 OOM内存溢出案例
  • 设计模式-行为型模式-模板方法模式
  • 预训练语言模型的前世今生 - 从Word Embedding到BERT
  • 深入掌握Linux磁盘管理,从入门到精通的完整指南
  • 安装node版本管理工具(nvm)、利用nvm安装node
  • html+css+js网页设计 故宫7个页面 ui还原度100%
  • 解决App推广痛点:一键获取下载数据的秘诀
  • Vue(七) TodoList案例1.0
  • 新的Ubuntu服务器如何启用root账号和配置静态ip以及开启ssh服务
  • spark.sql
  • 数仓基础(九):各大公司实时数仓实践
  • Spring Security与Apache Shiro:Java安全框架的比较
  • 电信500M宽带+AX210无线网卡测速
  • charles使用ssl证书抓包https请求失败解决方案
  • JavaScript 如何正确处理 Unicode 编码问题!
  • 〔开发系列〕一次关于小程序开发的深度总结
  • 4月23日世界读书日 网络营销论坛推荐《正在爆发的营销革命》
  • ES6, React, Redux, Webpack写的一个爬 GitHub 的网页
  • HTTP--网络协议分层,http历史(二)
  • js操作时间(持续更新)
  • Mithril.js 入门介绍
  • MYSQL如何对数据进行自动化升级--以如果某数据表存在并且某字段不存在时则执行更新操作为例...
  • PHP变量
  • React Native移动开发实战-3-实现页面间的数据传递
  • SegmentFault 2015 Top Rank
  • 后端_MYSQL
  • 如何邀请好友注册您的网站(模拟百度网盘)
  • 什么是Javascript函数节流?
  • -- 数据结构 顺序表 --Java
  • 微信公众号开发小记——5.python微信红包
  • 源码之下无秘密 ── 做最好的 Netty 源码分析教程
  • ​用户画像从0到100的构建思路
  • #java学习笔记(面向对象)----(未完结)
  • #预处理和函数的对比以及条件编译
  • (4)事件处理——(6)给.ready()回调函数传递一个参数(Passing an argument to the .ready() callback)...
  • (翻译)Quartz官方教程——第一课:Quartz入门
  • (含react-draggable库以及相关BUG如何解决)固定在左上方某盒子内(如按钮)添加可拖动功能,使用react hook语法实现
  • (佳作)两轮平衡小车(原理图、PCB、程序源码、BOM等)
  • (简单有案例)前端实现主题切换、动态换肤的两种简单方式
  • (全部习题答案)研究生英语读写教程基础级教师用书PDF|| 研究生英语读写教程提高级教师用书PDF
  • (一)SpringBoot3---尚硅谷总结
  • (原)本想说脏话,奈何已放下
  • (转)关于pipe()的详细解析
  • (转)使用VMware vSphere标准交换机设置网络连接
  • (最简单,详细,直接上手)uniapp/vue中英文多语言切换
  • .bat批处理(九):替换带有等号=的字符串的子串
  • .md即markdown文件的基本常用编写语法
  • .NET Reactor简单使用教程
  • .NET 跨平台图形库 SkiaSharp 基础应用
  • .NetCore发布到IIS
  • .NET简谈设计模式之(单件模式)
  • .NET与 java通用的3DES加密解密方法
  • []T 还是 []*T, 这是一个问题
  • [1127]图形打印 sdutOJ