1. 前言
由于C语言的标准库不够强大
没有数据结构和一些基本算法
什么都需要程序员自己实现
所以C语言在某种意义上并不实用
本章重点:
本章会简单介绍STL的各个版本
STL的六大组件和怎样学STL
STL的缺陷
重点讲解string的使用
熟悉string的重要接口
目标是讲完能够独自使用string库
2. STL库的版本以及缺陷
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要阅读部分源代码主要参考的就是这个版本
比较重要的是P.J版和SGI版
一个被Windows系统采用
一个被Linux系统采用
STL库的缺陷:
- STL库的更新太慢了。
这个得严重吐槽,上一版靠谱是C++98,中间的C++03基本一些修订。C++11出来已经相隔了13年,STL才进一步更新。 - STL现在都没有支持线程安全。
并发环境下需要我们自己加锁。且锁的粒度是比较大的。 - STL极度的追求效率,导致内部比较复杂。比如类型萃取,迭代器萃取。
3. STL库的六大组件
请看下图:
后期对于STL的学习将按照以下顺序:
- 进阶内容:
各种算法
string vector
list stack
queue deque
priority_queue
仿函数
- 高阶内容:
map和set
AVL数和红黑树
哈希相关
4. string的使用
首先,所有的STL库函数的使用都要查看
C++字典来学习接口函数,并且模拟实现
先看string解释(不懂可以翻译)
简单来说,string是表示字符串的
字符串类
该类的接口与常规容器的接口基本相同
再添加了一些专门用来操作string的常规操作
4.1 string类对象常见构造
一共有七个构造函数,但实用的有下面5个
用一个字符串构造
string str("abcdefg");
用一个字符构造
string str('w');
用n个字符c构造
string str(10,'x');
用一段迭代器区间构造
string tmp("abcdefg"); string str(tmp.begin(),tmp.end());
拷贝构造
string tmp("abcdefg"); string str(tmp);
注:迭代器类似于指针,在string和
vector中,迭代器就是普通指针
在后期会介绍迭代器的概念
5. string类对象的容量操作
请看下图:
string的内部实现中有size
和capacity两个和容量相关的变量
size代表字符串有效长度
capacity代表字符串的实际长度
5.1 size和capacity接口函数
size和capacity函数比较简单
可自行查看接口函数的返回值,参数
使用方法:
string str("abcdefg"); int size = str.size(); int capacity = str.capacity();
切记要加上括号!
size和capacity是成员函数
用.
或者->
访问
5.2 empty和clear函数
empty函数十分简单
若类对象是空串,就返回true
若不是空串就返回false
clear需要注意的点:
- clear后,使用empty会返回true
- clear函数只将size清零
- clear函数不会改变capacity
5.3 resize和reserve函数
resize函数需要注意的点:
- 此函数既能改变size也能改变capacity
- 在不初始化的情况下直接将size扩为n
- 将size扩为n并且用n个字符c初始化
reserve函数需要注意的点:
- 此函数只改变capacity不改变size
6. 迭代器以及string的访问和遍历
迭代器: iterator
像指针一样的类型,用法和指针相似
- 函数begin返回第一个位置的迭代器
- 函数end返回size位置的迭代器
迭代器的使用:
string str("abcdefg"); string::iterator it = str.begin(); while(it != str.end()) { cout<<*it<<endl; it++; }
迭代器可以像指针一样++和–
也可以解引用拿到指向的内容
6.1 运算符重载[ ]
它可以让我们像使用数组一样
随机访问string类对象中的字符
比如:
string str ("Test string"); for (int i=0; i<str.size(); ++i) { cout << str[i]; }
并且string类会检查[]是否越界
- string不喜欢用迭代器,因为[]更好用
- vector也不喜欢用迭代器,[]更好用
- list不能用[],因为它不支持随机访问
6.2 反向迭代器和范围for
反向迭代器: reverse_iterator
顾名思义是倒着走的迭代器
和反向迭代器相对应的是
rbegin和rend函数
使用方法:
string s("abcdefg"); string::reverse_iterator rit = s.rbegin(); while(rit != s.rend()) { cout<<*rit; rit++; }
rit++是往前走,会打印gfedcba
支持了迭代器后就可以使用范围for遍历:
string str("abcdefg"); for(auto ch : str) { cout<<ch; }
7. string类对象的修改操作
首先,npos是int的最大值
append不常用,+=很常用!
push_back使用:
string str("abcde"); str.push_back('f'); str.push_back('g'); //str现在是:abcdefg
接口函数:operator+=
此函数可以+=一个字符或一个字符串
甚至是一个string类对象:
string tmp("hij"); string str("abc"); str+='d'; str+="efg"; str+=tmp; //str现在为:abcdefghij
7.1 c_str和find函数
c_str函数返回字符串从\0结尾的字符串
但是c++中的字符串不一定以\0结尾
c++中字符串类以size为准来结尾
所以它叫:c_str
,是c语言的规则
下面这段代码可以自己理解一下:
string filename("test.cpp"); cout << filename << endl; cout << filename.c_str() << endl; filename += '\0'; filename += "string.cpp"; cout << filename << endl; // string 对象size为准 cout << filename.c_str() << endl; // 常量字符串对象\0
find函数比较简单
大家阅读文档就应该知道这是啥意思
8. insert和erase函数
insert函数可以在pos位置插入
一个字符或者一个字符串或者
一个string类,甚至还可以指定插入
字符串的长度,接口很多,需要自己理解
erase函数可以删除从pos位置
往后len个字符,若erase函数全用
缺省参数,则从0位置删除npos个
也就是将字符全部删除完
甚至可以删除一段迭代器区间
9. 总结以及拓展
string类需要我们单独拿出来学习
这是因为STL库函数中很多接口
都是相似的,学习了string后
会对vector和list等等容器的学习有帮助
vector的接口函数:
不能说和string一模一样
只能说和string完全相同
大家有兴趣可以自行去搜vector和list
拓展题目以及阅读
学完string后可以尝试做一下简单题:
拓展阅读
string类的operator<</ operator>>/ getline
🔎 下期预告:vector的接口函数 🔍