一、STL(standard template libaray-标准模板库):是C++标准库的重要组成部分,不仅是一个可复用的组件库,而且是一个包罗数据结构与算法的软件框架。
二. 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的六大组件
四、stl的缺陷
STL库更新慢。上一版靠谱是C++98,中间的C++03基本一些修订。C++11出来已经相隔了13年,STL才进一步更新。
**STL现在都没有支持线程安全。**并发环境下需要我们自己加锁。且锁的粒度是比较大的。
**STL极度的追求效率,导致内部比较复杂。**比如类型萃取,迭代器萃取。
**STL的使用会有代码膨胀的问题。**比如使用vector/vector/vector这样会生成多份代码,当然这是模板语法本身导致的。
C语言中,字符串是以’\0’结尾的一些字符的集合,为了操作方便,C标准库中提供了一些str系列的库函数,但是这些库函数与字符串是分离开的,不太符合OOP的思想,而且底层空间需要用户自己管理,稍不留神可能还会越界访问。
string是表示字符串的字符串类。
该类的接口与常规容器的接口基本相同,再添加了一些专门用来操作string的常规操作。
string在底层实际是:basic_string模板类的别名,typedef basic_string
不能操作多字节或者变长字符的序列。在使用string类时,必须包含#include头文件以及 using namespace std;
ASCALL-美国信息交换标准编码
编码:计算机存值(01)–对应关系–文字符号
然而ascall码的一个字符只占用1个字节【2^8-256】种对应关系,仅仅能满足美国(英文)的需求。
所以ascall码并不能满足我们博大精深的汉字。随之运营而生的出现了万国码(又称统一码)
万国码
其中有UTF-8(兼容ascall码)-最常用,UTF-16,UTF32
咱们中国也编了一套计算机编码-GBK字库-专门针对中文的编码(双字符编码)
GBK
函数名称 | 功能 |
---|---|
string()【括号省略则为无参字符串】 | 空字符串 |
string(const char*s) | 用字符串来构造string对象 |
string(size_t,char c) | 用size_t个字符c来构造string对象 |
string(const string&s) | 拷贝构造函数 |
演示如下图
注意:反向迭代器用的rbigin()和rend()要搭配出现!
到这里会有人吐槽道这一串代码也太长了,迭代器真不好用…;这里有接收到s1.begin( )的返回值,那就可以用auto通过返回值推导类型拉!
综上我们可以作出迭代器表格总结
迭代器(都可以用auto推导) | 非const | const |
---|---|---|
正向 | (正向)可遍历可读可写begin(),end() | (正向)可遍历可读不可写cbegin(),cend() |
反向 | (反向)可遍历可读可写rbegin(),rend() | (反向)可遍历可读不可写crbegin(),crend() |
通过这里我们还可以总结一个规律:
需要的功能 | 实现 |
---|---|
可读可写 | 实现可读(cosnt) 和可写两个版本 |
只可读不需要可写 | *实现*可读(const)一个版本 |
只需要可写不需要可读 | 实现可写版本 |
函数名称 | 功能(单位:字节) |
---|---|
size | 返回字符串有效长度 |
length | 返回字符串有效长度 |
capacity | 返回空间(容量)总大小 |
max_size | 返回可用最大空间大小(42亿9千万) |
clear | 清除有效字符 |
reverse(n) | 为字符串预留n个空间 |
resize(n,初始化的内容) | 把有效字符个数改为n个,若有初始化的内容则在有效字符之后的空间用其填充;初始化的内容省略时,则用/0(/0不显示)填充,。 |
empty | 检查字符串是否为空,若为空则返回true,不为空则返回false |
shrink_to_fit | 把字符串的capacity减少或增加为满足size大小的容量 |
因此我们做出resize功能的表格
resize(n) | |
---|---|
n |
从后往前只保留n个当前有效字符 |
size |
size |
n>capacity | 对字符串扩容,size和capacity增大 |
这里可以对照各个接口查看文档
在这里我们也列一个表格
push back | 在字符串尾插字符 |
---|---|
append | 在字符串后追加一个字符串 |
operator+= | 在字符串后追加字符、字符串str或者已有字符串(即同时具备push_back和append的功能)因此是最常用的 |
insert(size_t pos,const string& str) | 在pos位置插入字符串或者字符(较为常用) |
assign | 给字符串赋值 |
replace | 替换字符串 |
c_str | 返回c格式字符串(或者返回指向c格式字符串的指针) |
find(pos,‘c’)+npos | 从字符串pos位置开始往后找字符c,找到返回该字符c下标,没有则返回npos |
rfind(pos,‘c’)+npos | 从字符串pos位置开始往前找字符c,找到返回该字符c下标,没有则返回npos |
substr(pos,n) | 从pos位置开始,往后截取n个字符,作为字符串返回,不给n则以缺省值输出到结尾 |
我们对psuh_back的功能进行刨析:
在这里我们可以做个实验,初始化一个字符串s,然后一直往字符串里尾插字符c,尾插1000次,然后检测字符串容量;我们可以看到右边显示每次字符串容量扩容是大概按照1.5倍capacity开辟的(vs编译器底下开辟容量只考虑有效字符串大小,不考虑/0)。
我们知道push_back会在插入字符之前先检查空间够不够大小,不够会去扩容,而这里会造成多次开辟空间,会造成很大的损失。如果我们提前知道了要存入字符串大小呢?是不是可以预先在push_back之前先开辟一块空间,然后再往这块空间尾插呢?
这里就要用到上面提到的reserve;这样就不用多次开辟空间,减少损害。
assign是清空字符串所有内容,然后再将新内容填充;replace是替换文本,可以不清空所有内容。
leetcode上面有一题:把空格换成%20;当时用c写非常难受,现在咱用c++写一下。
find的常用接口:find(要找的内容,找的起始位置(没写则默认从第一个位置开始找)):在字符串里面找相应内容,找到了返回下标,没找到返回npos;
是不是舒服了很多呀!
void test_string11()
{
//c_str作为指针用-可以打印该test.c文件的内容
{
string file("test.cpp");
FILE* fout = fopen(file.c_str(), "r");
assert(fout);
char ch = fgetc(fout);
while (ch != EOF)
{
cout << ch;
ch = fgetc(fout);
}
fclose(fout);
}
}
getline | 以/n为结尾获取一行字符 |
---|
对于string类的第一次见面到这里为止了;这次鸽了半个月没有更新博客,现在回来继续更新优质内容!(坚决不当,从我做起!)