当前栏目
【C++】STL简介 及 string的使用
文章目录
1. STL简介
1.1 什么是STL
STL
(standard template libaray-标准模板库):是C++标准库的重要组成部分,不仅是一个可复用的组件库,而且是一个包罗数据结构与算法的软件框架。
1.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要阅读部分源代码,主要参考的就是这个版本。
1.3 STL的六大组件
这个大家先了解一下,我们后面都会慢慢的进行学习。
2. string类的使用
2.1 C语言中的字符串
C语言中,字符串是以’ ’结尾的一些字符的集合,为了操作方便,C标准库中提供了一些str系列的库函数,但是这些库函数与字符串是分离开的,不太符合OOP的思想,而且底层空间需要用户自己管理,稍不留神可能还会越界访问。
在OJ中,有关字符串的题目基本以string类的形式出现,而且在常规工作中,为了简单、方便、快捷,基本都使用string类,很少有人去使用C库中的字符串操作函数。
2.2 标准库中的string类
那标准库中的string到底是个啥呢?
🆗,它其实是一个类模板实例化出来的一个模板类。
string类的文档介绍
我们可以看到,它其实是basic_string
这个类模板实例化出来的类的一个typedef
。
ps:这个页面翻译有些地方可能不恰当。
可以看到,basic_string
实例化出来的模板类除了string
还有三个。
它们都是basic_string
这个类模板实例化出来的模板类,区别在于它们对应的模板参数的类型不同。
那对于这个string类呢?
其实它的底层就是一个动态的字符数组,就像我们之前数据结构写的顺序表。
那string呢就是一个char
类型的字符数组,wstring就是对应的wchar_t
的字符数组
u16string就是char16_t
的字符数组,u32string就是char32_t
的字符数组。
那这些不同类型的字符对应的大小也是不同的。
欸!那大家现在有没有一个疑问,为什么搞出这么多种的string类呢?
🆗,那我们在C语言阶段有了解过ASCII编码:
这里面的所有符号和字母都一个对应的ASCII码值。
那问一下大家假如现在我们要存一个字符串
char str[] = "hello";
那它在内存中存的是啥?
我们看到内存里存的并不是字母本身,而是它们对应的ASCII码值(这里以16进制显示)。
那我们去打印的时候呢其实它也是去对照这个表找到这个ASCII码对应的字母然后显示。
所以呢
ASCII其实主要是来显示英语这些语言的。
那这样的话,随着计算机的发展,只有一个ASCII编码还够用吗?
是不是就不行了啊,因为世界上还有很多国家,很多种语言呢。比如现在我们要让计算机能显示中文,用ASCII码是不是就不行了啊。而且ASCII只定义了128个字符(一个字节就够用了),中国的汉字大约有10万个呢!
那基于这样的原因呢,有人就又发明了Unicode——万国码(兼容ASCII):
但是呢各个国家的情况也不同,有的国家文字少,有的多,所以Unicode又进行了划分,分为UTF-8、UTF-16、UTF-32
这些。
所以呢,为了应对这些不同的编码,就产生了这些不同的字符类型,所以就有了basic_string
这个泛型字符串类模板,我们可以用它实例化出不同类型的字符串类。
🆗,那这里面最常用的呢其实还是string
。
- string是表示字符串的字符串类
- 该类的接口与常规容器的接口基本相同,再添加了一些专门用来操作string的常规操作。
- string在底层实际是:basic_string模板类的别名,
typedef basic_string<char, char_traits, allocator> string
;- 不能操作多字节或者变长字符的序列。
在使用string类时,必须包含#include头文件以及using namespace std
2.3 string类的常用接口说明
1. string类对象的常见构造
(constructor)函数名称 | 功能说明 |
---|---|
string() 空字符串构造函数(默认构造函数) | 构造一个空字符串,长度为零个字符 |
string (const char* s) | 用一个常量字符串来构造字符串类对象 |
string (const string& str, size_t pos, size_t len = npos) (用的不多) | 复制 str 中从字符位置 pos 开始并跨越 len 字符的部分(如果 str 太短或 len 是string::npos,则直到 str 的末尾) |
string (const char* s, size_t n) | 拿s指向字符串的前n个字符去构造string对象 |
string (size_t n, char c) | 拿n个字符c去构造string对象 |
string (const string& str) | 拷贝构造 |
template <class InputIterator> string (InputIterator first, InputIterator last) | 涉及到迭代器,后面再说 |
先来看string()
:
构造一个空字符串。
string (const char* s)
:
另外呢,这里还支持这样写:
那这个我们之前是不是讲过啊,单参数的构造函数是支持隐式类型转换的。
string (const string& str, size_t pos, size_t len = npos)
:
这个怎么用呢?
它其实是拿str
中的一个子串去去构造string对象,这个字串是从str中下标pos位置开始,长度为len的一个字串。
那这个地方还说了,如果这里的str
比较短,或者这里给的len
是string::npos
,则这个字串一直到str
的末尾。
什么意思呢?
举个栗子:
我们现在的len是50,那这时字符串的长度是不是不够啊,比50短,那这个时候怎么办,会报错了?
不会的,这里它会取到字符串的结尾位置:
那我们看到这里还说如果给的len是string::npos
,也会一直到str末尾,而且我们发现:
这里的参数len给的是有缺省值的,而这个缺省值就是npos
,那这个npos
是个啥呢?
我们看到它是一个静态成员变量,值是-1,但是呢,因为这里它的类型是size_t
(无符号整型),所以它在这里其实是整型的最大值:
而我们的字符串长度是不可能大于这个值的,所以这里也是会取到结尾。
这个其实用的不是很多,但这里第一次见,带大家了解一下。
string (const char* s, size_t n)
:
拿s指向字符串的前n个字符去构造string对象
string (size_t n, char c)
:
拿n个字符c去构造string对象
string (const string& str)
:
拷贝构造:
2. string类对象的容量操作
总共呢有这么多。
首先我们看到有个size,还有个length:
都是返回字符串长度。
欸!那他们俩的功能一样,为什么要搞两个呢?搞一个size,搞一个length。
🆗,那这里呢其实跟一些历史原因有关,string呢其实出现的比STL早,string其实严格来说是不属于STL的,它是C++标准库产生的,在STL出现之前就已经在标准库出现了。
那string呢其实最早之前设计的就是length,因为字符串的长度嘛,用length就很合适。但是后面STL出现之后,里面的其它数据结构用的都是size,那为了保持一致,就给string也增加了一个size。
所以size()与length()方法底层实现原理完全相同,引入size()的原因是为了与其他容器的接口保持一
致,一般情况下基本都是用size()。
然后我们看到有一个max_size
:
它的作用呢是返回字符串的最大长度
但是呢,真正在实际中字符串可以并不能开这么长,而且在不同平台下这个值也可能不一样。
所以这个东西大家了解一下,知道有这么个东西就行了。
然后我们来看一下capacity
:
capacity
呢其实就是返回当前string对象的容量(即当前给它分配的空间有多大),我们之前学过数据结构,相信这个大家很好理解。
我们看到这里返回的s的容量是15,但是呢这里想告诉大家VS下面这里它是不包含给'