【C++】STL简介 | STL六大组件 | string类 | string类对象操作

目录

1. 什么是STL

2. STL的版本 

3. STL的六大组件

4. STL的缺陷

5. 引出string类

6. 标准库中的string类

6.1 string类简介

6.2 string类对象的构造

6.3. string类对象的容量

6.4. string类对象的遍历

6.5. string类对象的修改

6.6. string类非成员函数

6.7. vs和g++下string结构的说明


1. 什么是STL

  • STL(standard template libaray-标准模板库):是C++标准库的重要组成部分,不仅是一个可复用的组件库,而且是一个包罗数据结构与算法的软件框架。
  • STL是C++标准库的一部分。

2. STL的版本 

◆ 原始版本
Alexander Stepanov、Meng Lee 在惠普实验室完成的原始版本,本着开源精神,他们声明允许任何人任意运用、拷贝、修改、传播、商业使用这些代码,无需付费。唯一的条件就是也需要向原始版本一样做开源使用。 HP 版本--所有STL实现版本的始祖。

◆ P. J. 版本
由P. J. Plauger开发,继承自HP版本,被Windows Visual C++采用,不能公开或修改,缺陷:可读性比较低,符号命名比较怪异。

◆ RW版本
由Rouge Wage公司开发,继承自HP版本,被C++ Builder采用,不能公开或修改,可读性一般。

◆ SGI版本
由Silicon Graphics Computer Systems,Inc公司开发,继承自HP版本。被GCC(Linux)采用,可移植性好,可公开、修改甚至贩卖,从命名风格和编程风格上看,阅读性非常高。我们后面学习STL要阅读部分源代码,主要参考的就是这个版本。

3. STL的六大组件

4. STL的缺陷

  1. STL库的更新太慢了。这个得严重吐槽,上一版靠谱是C++98,中间的C++03基本一些修订。C++11出来已经相隔了13年,STL才进一步更新。
  2. STL现在都没有支持线程安全。并发环境下需要我们自己加锁。且锁的粒度是比较大的。
  3. STL极度的追求效率,导致内部比较复杂。比如类型萃取,迭代器萃取。
  4. STL的使用会有代码膨胀的问题,比如使用vector/vector/vector这样会生成多份代码,当然这是模板语法本身导致的。

5. 引出string类

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

6. 标准库中的string类

6.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;

6.2 string类对象的构造

(constructor)函数名称

功能说明

string()   

构造空的string类对象,即空字符串

string(const char* s)   

用字符串来构造string类对象

string(const string &s)   

拷贝构造函数

string (const string& s, size_t pos, size_t len = npos);

从第pos个位置拷贝npos个

string(size_t n, char c)

string类对象中包含n个字符c

void Teststring()
{
	string s1;                //构造空的string类对象s1
	string s2("hello word");  //用字符串构造string类对象s2
	string s3(s2);            //拷贝构造s3
	string s4(s2,5,3);        //拷贝构造s2,从第5个位置开始(从0开始)取3个字符
	string s5(s2,5,10);	      //拷贝构造s2,从第5个位置开始,取10个字符,不够,有多少取多少
	string s6(s2,5);          //拷贝构造s2,从第5个位置开始,取余下的

	cout << s1 << endl;
	cout << s2 << endl;
	cout << s3 << endl;
	cout << s4 << endl;
	cout << s5 << endl;
	cout << s6 << endl;
}

int main()
{
	Teststring();
	
	return 0;
}

6.3. string类对象的容量

函数名称

功能说明

size  (重点)

返回字符串有效字符长度

length

返回字符串有效字符长度

capacity

返回空间总大小

empty   (重点)

检测字符串释放为空串,是返回true,否则返回false

clear   (重点)

清空有效字符

reserve   (重点)

为字符串预留空间

resize   (重点)

将有效字符的个数该成n个,多出的空间用字符c填充

void Teststring2()
{
	string s1("hello word");

	for(size_t i=0;i<s1.size();i++)
	{
		cout << s1[i] << " ";			  //这里的[]实际是调用的运算符重载
		cout << s1.operator[](i) << " ";  //[]运算符重载
	}
	cout << endl;
	cout << s1.size() << endl;
	cout << s1.capacity() << endl;
}

int main()
{
	Teststring2();
	
	return 0;
}

查看扩容机制: 

void Teststring5()
{
	//查看扩容机制
	string s;
	size_t sz = s.capacity();
	for(int i=0;i<100;i++)
	{
		s.push_back('c');
		if(sz != s.capacity())
		{
			sz = s.capacity();
			cout << "capacity changed: " << sz << 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 res_arg=0):为string预留空间,不改变有效元素个数,当reserve的参数小于 string的底层空间总大小时,  reserver不会改变容量大小。
6.4. string类对象的遍历

函数名称

功能说明

operator[ ]   

返回pos位置的字符,  const string类对象调用

begin+ end

begin获取一个字符的迭代器 + end获取最后一个字符下一个位置的迭 代器

rbegin + rend

begin获取一个字符的迭代器 + end获取最后一个字符下一个位置的迭 代器

范围for

C++11支持更简洁的范围for的新遍历方式

用迭代器遍历

void Teststring3()
{
	string s1("hello word");
	const string s2("hello word");

	string::iterator it1 = s1.begin();   //begin为开始位置
	while(it1 != s1.end())				 //end为最后的下一个位置
	{
		cout << *it1 << " ";
		++it1;
	}

	string::const_iterator it2 = s2.begin();   //const迭代器,只读,不可以修改
	while(it1 != s2.end())				
	{
		cout << *it2 << " ";
		++it2;
	}

}

void Teststring4()
{
	string s1("hello word");

	string::reverse_iterator rit = s1.rbegin();  //反向迭代器
	while(rit != s1.rend())				 
	{
		cout << *rit << " ";
		++rit;
	}
}
6.5. string类对象的修改

函数名称

功能说明

push_back

在字符串后尾插字符

append

在字符串后追加一个字符串

operator+= (重点)

在字符串后追加字符串

c_str(重点)

返回C格式字符串

find + npos(重点)

从字符串pos位置开始往后找字符c,返回该字符在字符串中的位置

rfind

从字符串pos位置开始往前找字符c,返回该字符在字符串中的位置

substr

在str中从pos位置开始,截取n个字符,然后将其返回

void Teststring4()
{
	string s1("hello word");
	s1.push_back('!');
	cout << s1 << endl;

	s1.append("hello bit");
	cout << s1 << endl;

	s1.append(10,'x');
	cout << s1 << endl;
 
}

find 和 substr的用法举例: 

void Teststring6()
{
	string s1("test.c");
	size_t pos1 = s1.find('.');
	if(pos1 != s1.npos)
	{
		string suffix = s1.substr(pos1);
		cout << suffix << endl;
	}
	else
	{
		cout << "找不见" << endl;
	}
}

注意:

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

函数

功能说明

operator+

尽量少用,因为传值返回,导致深拷贝效率低

operator>>   (重点)

输入运算符重载

operator   (重点)

输出运算符重载

getline   (重点)

获取一行字符串

relational operators   (重点)

大小比较

6.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;

◆ 这种设计也是有一定道理的大多数情况下字符串的长度都小于16string对象创建好之后部已经有了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;
};   

本章完。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

品优购首页制作

一&#xff0c;常用模块类名命名 二&#xff0c;快捷导航shortcut制作 三&#xff0c;header制作 3.1LOGO SEO优化 3.2 搜索模块定位 四&#xff0c; nav导航制作 五&#xff0c;footer底部制作 六&#xff0c;main主体模块制作 以前书写是模块化中的公共部分 main主体模块是…

GEE入门篇|图像分类(一):监督分类

在遥感中&#xff0c;图像分类是尝试将图像中的所有像素分类为有限数量的标记土地覆盖和/或土地利用类别。 生成的分类图像是从原始图像导出的简化专题图&#xff08;图 1&#xff09;&#xff0c; 土地覆盖和土地利用信息对于许多环境和社会经济应用至关重要&#xff0c;包括自…

鸿蒙开发,对于前端开发来说,究竟是福是祸呢?

提前声明&#xff1a; 先说好哈&#xff0c;不要一上来就开喷&#xff0c;好吧&#xff0c;不感兴趣的话你可以不用看下文直接划走&#xff0c;直接喷俺有点承受不住&#xff0c;心脏不好。如果你感兴趣&#xff0c;你可以先把这篇文章看完&#xff0c;看完后感觉俺讲的还挺有道…

堆和二叉树的动态实现(C语言实现)

✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅ ✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨ &#x1f33f;&#x1f33f;&#x1f33f;&#x1f33f;&#x1f33f;&#x1f33f;&#x1f33f;&#x1f33f;&#x1f33f;&#x1f33f;&#x1f33f;&#x1f33f;&#x1f33f;&#x1f33f;&#x1…

Linux - 基础IO

1、回顾 1.1、来段代码回顾C文件接口 hello.c写文件 #include <stdio.h> #include <string.h> int main() {FILE *fp fopen("myfile", "w");if(!fp){printf("fopen error!\n");}const char *msg "hello bit!\n";int …

xss.haozi.me:0x03及04

这里有一个正则所以&#xff08;&#xff09;要用到实体编码 <a href"javascript:alert1">cc</a> 03 04都一样

在线客服系统部署ssl开启https无法自动获取提示消息解决办法

▇ 增加https无法收发消息&#xff1a; 严格按照教程修改 1./站点目录/public目录下,修改index.php define(whost,wss://kf.tpym.cn); define(wport,443); 2./站点目录/service 目录下,修改config.php // websocket 端口&#xff0c;客服系统网页会连这个端口 $websocket_…

防患未然,OceanBase巡检工具应用实践——《OceanBase诊断系列》之五

1. OceanBase为什么要做巡检功能 尽管OceanBase拥有很好的MySQL兼容性&#xff0c;但在长期的生产环境中&#xff0c;部署不符合标准规范、硬件支持异常&#xff0c;或配置项错误等问题&#xff0c;这些短期不会出现的问题&#xff0c;仍会对数据库集群构成潜在的巨大风险。为…

1999-2022年30省平均受教育年限(含原始数据和具体计算过程+计算结果)

1999-2022年30省平均受教育年限&#xff08;含原始数据和具体计算过程&#xff09; 1、时间&#xff1a;1999-2022年 2、范围&#xff1a;30省&#xff08;剔除西藏&#xff09; 3、计算方式&#xff1a;平均受教育年限&#xff08;未上学人数*0小学人数*6初中人数*9高中人数…

AI大模型的预训练、迁移和中间件编程

大家好&#xff0c;我是爱编程的喵喵。双985硕士毕业&#xff0c;现担任全栈工程师一职&#xff0c;热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。现为CSDN博客专家、人工智能领域优质创作者。…

python.模块与包

1.模块是什么 本质上是一种python文件&#xff0c;以.py结尾&#xff0c;里面有类&#xff0c;函数&#xff0c;变量等&#xff0c;认为这是一个工具包&#xff0c;每个模块有不同的功能&#xff0c;导入后可以直接使用 2.模块的导入 方法1 import 模块名 使用&#xff1a…

展示模型展台的高度一般为多少---模大狮模型网

展示模型展台的高度一般取决于多个因素&#xff0c;包括展示物品的大小、展台的设计风格、展览场地的限制等。一般来说&#xff0c;展示模型展台的高度可以根据以下几点考虑&#xff1a; 展示物品的大小&#xff1a;如果展示物品比较大或需要竖立展示&#xff0c;展台的高度可能…

GraphGeo参文19:Auto-Encoding Variational Bayes

https://arxiv.org/abs/1312.6114 [19] Diederik P Kingma and Max Welling. 2014. Auto-encoding variational bayes. In ICLR. 【前言】:VAE模型是Kingma(也是Adam的作者)大神在2014年发表的文章,是一篇非常非常经典,且实现非常优雅的生成模型,同时它还为bayes概率图模型…

LVS负载均衡集群——NAT地址转换模式与DR直接路由

目录 一、LVS集群基本介绍 1、集群是什么&#xff1f; 2、集群的类型 ①负载均衡集群 ②高可用群集 ③高性能运算群集 3、负载均衡集群的结构 第一层&#xff0c;负载调度器 第二层&#xff0c;服务器池 第三层&#xff0c;共享存储 4、LVS负载均衡集群的三种工作模…

学习计算天数

学习计算天数 题目描述&#xff1a;解法思路&#xff1a;解法代码&#xff1a;运行结果&#xff1a; 题目描述&#xff1a; 输入y和m两个整数&#xff0c;y表示年份&#xff0c;m表示月份&#xff0c;计算y年m月有多少天&#xff0c;并输出天数。 测试1&#xff1a; 输⼊&…

Redis常见的15个【坑】,避坑指南

一、常见命令 1.1 过期时间意外丢失 原因&#xff1a; SET命令如果不设置过期时间&#xff0c;那么Redis会自动【擦除】这个key的过期时间 1.2 DEL命令阻塞redis key是String类型时&#xff0c;DEL时间复杂度是O(1)key是List/Hash/Set/ZSet类型&#xff0c;DEL时间复杂度是…

FRM模型十五:净值归因之Fama_French三因子模型

文章目录 一、起源二、构建因子三、投资组合的净值归因1. 市场因子2. 规模因子3.价值因子4. 基于净值的归因方法 三、代码实现 一、起源 在多因子模型推出之前&#xff0c;CAPM模型被视为资产定价的第一标准。随着市场不断发展&#xff0c;发现了越来越多CAPM模型无法解释的现…

Microsoft@ppt@快速掌握核心功能@常用功能培训

文章目录 refs动画动画的用途逐部分显示内容实现问答效果部分地修改页面内容动画效果 常用窗口对象选择窗口&#x1f47a;批量选择对象 如何为重叠的对象高效的命名重命名方式方案1方案2对象重命名原则重命名后如何使用tips 动画窗口&#x1f47a; 幻灯片管理幻灯片母版幻灯片母…

【软件测试】一个扫码支付的二维码怎么测(测试点分析)

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 面试的时候&#…

VS统计代码行数

1.使用查找和替换方式 按CTRLSHIFTF (Find in files)&#xff0c;勾上支持正则表达式&#xff0c; 然后输入搜索内容&#xff1a;^:b*[^:b#/].*$ 如图所示&#xff1a; 2.查看查询结果 需要注意&#xff1a;#开头和/开头或者空行都不计入代码量。