文章目录- 一、STL的简述
- 1.STL的框架
- 2.STL版本
- 二、编码铺垫
- 三、string类
- 四、常见构造
- 五、operator[]
- 六、访问及遍历
- 七、iterator迭代器
- 1.正向迭代器
- 2.反向迭代器
- 3.const迭代器
- 八、Capacity容量操作
- 1.常用接口
- 2.扩容问题
- 九、Modifiers修改操作
- 十、非成员函数重载
- 十一、总结
- 1.STL的框架
- 2.STL版本
- 1.正向迭代器
- 2.反向迭代器
- 3.const迭代器
- 1.常用接口
- 2.扩容问题
一、STL的简述
STL(standard template libaray-标准模板库):是C 标准库的重要组成部分**,不仅是一个可复用的组件库,而且一个包罗数据结构与算法的软件框架**。
1.STL的框架
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要阅读部分源代码,主要参考的就是这个版本。
对于STL的学习我们可以前去官网看文档,多了解了解cplusplus.com
二、编码铺垫
string类本身就是一个模板,为什么要把string写成模板?是因为字符串的数组涉及编码问题,字符数组编码不同。所以需要模板
u16string:表示两个字节
u32string:表示四个字节
这里简单了解一下编码
- ✨ASCII码
美国信息交换标准码。
ASCII码表是计算机存值和文字符号的对应关系
只有256个字符
- ✨Unicode
万国码
Unicode是为了解决传统的字符编码方案的局限而产生的,它为每种语言中的每个字符设定了统一并且唯一的二进制编码
包括了utf-8,utf-16,utf-32
utf-8兼容了ASCII,utf-8使用比较普遍,也比较节省空间
- ✨gbk
gbk即国标,针对中文而设计的编码。采用双字节编码。
三、string类
根据不同的编码选用不同的string(接口是差不多的),这里我们只需重点学习string(utf-8):
string类模板的大概框架:
代码语言:javascript复制template <class T>
//动态增长字符数组
class basic_string
{
private:
T* _str;
size_t _size;
size_t _capacity;
};
使用string类的时候,我们要包含头文件#include
下面我们开始说一说string类常用的接口,对于常用接口我们需要熟练使用,其他的即可查阅学习。
四、常见构造
废话不多说,我们直接来使用一下这些构造函数,形成初步了解:
代码语言:javascript复制#include <iostream>
#include <string>
using namespace std;
void test_test1()
{
string s1;//默认构造
string s2("hello string");//带参构造
s2 = "world";
string s3 = "hehe";//构造 拷贝构造----直接构造
string s4(s2);//拷贝构造
string s5 = s2;
string s6(10, 'X');//个数初始化
string s7("hello world", 5);//取前n个
string s8(s7, 2, 3);
cout << s1 << endl;
cout << s2 << endl;
cout << s3 << endl;
cout << s4 << endl;
cout << s5 << endl;
cout << s6 << endl;
cout << s7 << endl;
cout << s8 << endl;
}
int main()
{
test_test1();
return 0;
}
注意:string类对象可支持直接用cin和cout进行输入和输出,这是因为重载了流插入>>和流提取<<操作符
对于s8,如果取的长度过大,会发生什么?查看文档:
直到结束,并不会报错:
对于默认值npos:
这里的npos是-1,但是这里是无符号,实际并不是-1,是4294967295。
通过这里的构造函数,我们需要知道,对于一些细节东西我们是要学会去看文档的,对于学习文档是非常重要的。
五、operator[]
operator[] 返回pos位置的字符,const string类对象调用
实际上重载了[],让string类可以像数组一样访问。数组的[]的本质是解引用,而这里是调用函数:
代码语言:javascript复制char& operator[](size_t pos)
{
assert(pos<_size);//检查越界
return _str[i];
}
传引用返回,可读可改。支持修改返回值:我们通过代码来实现这一功能
代码语言:javascript复制#include <iostream>
#include <string>
using namespace std;
int main()
{
string s("123456");
//读
for (size_t i = 0; i < s.size(); i )
{
cout << s[i] << ' ';
}
cout << endl;
//改
for (size_t i = 0; i < s.size(); i )
{
s[i] = 1;
}
cout << s << endl;
return 0;
}
当然,对于const修饰的字符串肯定不能修改了。
六、访问及遍历
对于遍历操作,第一个方式就是我们上面所说的operator[],第二个方式就是范围for
七、iterator迭代器
对于遍历,除了上面2种方式,我们也可以采取迭代器。迭代器行为上像指针,但是却不一定是指针。对于string的遍历,最简单的肯定是第一种,为什么还要有迭代器的存在呢
- 为什么要有迭代器❓
迭代器的意义在于通用,所有容器都可以使用迭代器这种方式去进行遍历和修改。而对于string类,[]足矣
1.正向迭代器
迭代器提供了begin和end的函数:
代码语言:javascript复制#include <iostream>
#include <string>
using namespace std;
int main()
{
string s("123456");
//读
string::iterator it = s.begin();
while (it != s.end())
{
cout << *it << " ";
it;
}
cout << endl;
//写
it = s.begin();
while (it != s.end())
{
*it = 1;
it;
}
cout << s << endl;
return 0;
}
2.反向迭代器
反向迭代器提供了rbegin和rend:
代码语言:javascript复制#include <iostream>
#include <string>
using namespace std;
int main()
{
string s("hello world");
string::reverse_iterator rit = s.rbegin();
while (rit != s.rend())
{
cout << *rit << " ";
rit ;
}
cout << endl;
return 0;
}
3.const迭代器
就是加上const进行修饰。普通的迭代器可读可写,而const迭代器可读不可写,因为const修饰this指向的内容,不支持写
const迭代器也可分为正向迭代器和方向迭代器,提供给const对象使用:
代码语言:javascript复制void Print(const string& s)
{
string::const_iterator it = s.begin();
while (it != s.end())
{
cout << *it << " ";
it ;
}
cout << endl;
string::const_reverse_iterator rit = s.rbegin();
while (rit != s.rend())
{
cout << *rit << " ";
rit ;
}
cout << endl;
cout << endl;
}
int main()
{
string s("hello world");
Print(s);
return 0;
}
c 11还特意区别了普通迭代器和const迭代器提供了下面的接口,作为区分:
八、Capacity容量操作
1.常用接口
函数名称 | 功能说明 |
---|---|
size | 返回字符串有效字符长度 |
length | 返回字符串有效字符长度 |
capacity | 返回空间总大小 |
empty | 检测字符串释放为空串,是返回true,否则返回false |
clear | 清空有效字符 |
reserve | 为字符串预留空间(影响capacity) |
resize | 将有效字符的个数该成n个,多出的空间用字符c填充(影响size和capacity) |
//string类对象支持直接用cin和cout进行输入和输出
void Teststring1()
{
string s("hello world!");
cout << s.size() << endl;//12
cout << s.length() << endl;//12
cout << s.capacity() << endl;//15
cout << s << endl;
// 将s中的字符串清空,注意清空时只是将size清0,不改变底层空间的大小
s.clear();
cout << s.size() << endl;//0
cout << s.capacity() << endl;//15
// 将s中有效字符个数增加到10个,多出位置用'a'进行填充
// “aaaaaaaaaa”
s.resize(10, 'a');
cout << s.size() << endl;//10
cout << s.capacity() << endl;//15
// 将s中有效字符个数增加到15个,多出位置用缺省值'