C++的标准库主要包含两大类,首先是包含C的标准库的,当然,为了适应c++对一些C库进行了少许的修改和增加。最重要的当然是面向对象的c++库;而c++库又可以分成两大类,即面向对象的c++库和标准模板库,也就是题目中的STL。另外在此基础上,还要提醒同学们的是,除了上面的库,在各个平台的开发厂商中,还会针对实际情况,对标准库进行扩展,这些可以归纳为扩展库。
同时,随着c++标准的不断迭代,还推出了很多新的库,同学们需要不断的学习跟进,目前最新的c++标准为c++20。主流的c++标准库实现有GNU/Linux上的libstdc++;IOS的libc++;微软的CRT,android的libc++,当然在NDK有过很多c++的版本,不过后来都被删除了;其它包括uSTL,Apache等很多大公司也有自己的相关的c++库(这里就不能叫标准库了,虽然实现的目的是一样的)。下面是相关库的基本组成部分分类:
c库主要包括:
1、标准输入输出,比如stdin,stdout,stderr。
2、字符串处理,比如strcat,strcopy等。
3、内存管理,如果malloc等。
4、日期、时间和本地化等如ctime,time,localtime等。
5、数学相关函数,如pow,cos等。
6、系统和管理相关函数,它定义了和OS相关的信号和函数调用规则,如setjmp,va_start等。
7、异常和错误,最典型的就是errno。
8、其它辅助如一些宏定义等。
c++库主要包括:
1、标准的IO类,如std::cout,std::in,ofstream等。
2、必须要提到的std::string。
3、数值处理相关类,numeric的complex。
4、本地化库。
5、异常库。
6、其它。
7、STL(标准模板库)。
在后面的学习应用中将以STL为主,穿插学习标准库的其它用法。
STL标准模板库主要分类:
1、STL容器(Containers),包含顺序容器和关联容器以及无序容器
容器非常好理解,日常的容器可以盛纳各种液体和物品。而在STL的容器可以盛纳各种数据。它分为顺序容器和关联容器两大类,顺序容器是指读写按照容器内的元素位置进行操作。你可以理解成一个箱子里有好多小格子,你可以根据小格子的顺序来取到其中的内容。它主要包括向量(Vector),链表(List)和双端队列(deque);而关联容器则是需要通过一个键值(KEY)来读写容器的元素。在标准库里主要就是映射(map)和集合(set)。无序容器主要包括unordered_set和unordered_map。
2、STL迭代器(Iterators)
迭代器其实更好理解,就是一种可以通用在容器中的遍历访问的模板指针。就是一个数据访问的索引。
3、STL分配器(Allocators)
分配器其实就是为了方便对容器等的通用化内存管理,提供的一种内存分配管理机制,可以理解成一种STL中的内存池。
4、STL适配器(Adapters)
适配器这个概念有点意思,其实如果有过接口开发经验的可能更容易明白,两种不同的接口要想使用同一个数据体系,就需要写一个小模块来进行接口数据的统一,这个小模块就叫做适配器。它其实是一种设计模式,而这种思想体现在STL中,就成为了适配器。
5、STL仿函数(函数对象)(Functors)
仿函数,有的翻译成函数对象,这个更有意思,其实就是通过前面提到的重载运算符(),实现了类似于函数使用的机制。在c++11后,提供了更安全的std::function。
6、STL算法(Functors)
模板库最初其实就是为了实现算法而设计的,这个在《c++编程思想》中的“通用算法”中有过提及。算法可能是同学们最容易理解但最不容易掌握的一部分了。比如常见的查找,排序以及删除、复制等。
除了上面这些基础的分类,在c++的新版本中又增加了概念等相关的知识,有兴趣可以看看本公众号中c++20的新功能相关文章。
后面会对这些STL的基本容器和算法逐一进行分析,这里给出一个综合例子:
#include
#include
#include
#include
#include
#include
struct Data
{
int len = 0;
int type = 0;
};
//类似数组
void TestVector()
{
std::vector vec;
Data d1;
Data d2;
vec.emplace_back(d1);
vec.push_back(d2);
std::cout << "vector first:" << vec[0].len << std::endl;
std::cout << "vector size:" << vec.size() << std::endl;
}
//链表
void TestList()
{
std::list l;
l.push_back(3);
l.push_front(9);
l.emplace_back(6);
std::cout << "list first:" << l.front() << std::endl;
std::cout << "list size:" << l.size() << std::endl;
}
//队列
void TestQueue()
{
std::queue q;
q.emplace(10);
q.push(20);
q.push(30);
std::cout << "queue first:" << q.front() << std::endl;
q.pop();
std::cout << "queue first:" << q.front() << std::endl;
q.pop();
std::cout << "queue first:" << q.front() << std::endl;
q.pop();
}
int buf[] = { 10,9,21,68,96,11,11,11,88,199,36,96,60,126,19,168 };
void TestSort()
{
std::array arr = { 0,9,21,68,96,11,11,11,88,199,36,96,60,126,19,168 };
std::sort(arr.begin(), arr.end());
std::cout << " ordered reslut:" << std::endl;
for (int num = 0; num < 16; num++)
{
std::cout << arr[num] << " ";
}
std::cout << " " << std::endl;
}
void TestSearch()
{
std::sort(buf,buf+16);
bool result = std::binary_search(buf,buf+16, 199);
std::cout << "search result:" << result << std::endl;
}
void TestCopy()
{
int buf_dst[100] = {0};
std::copy(buf,buf+16,buf_dst);
std::cout << "copy result:" << std::endl;
for (auto& au : buf_dst)
{
std::cout << au << " ";
}
std::cout << " " << std::endl;
}
int main()
{
TestVector();
TestList();
TestQueue();
//排序
TestSort();
TestSearch();
TestCopy();
std::cout << "STL test project!" << std::endl;
}
运行结果是:
vector first:0
vector size:2
list first:9
list size:3
queue first:10
queue first:20
queue first:30
ordered reslut:
0 9 11 11 11 19 21 36 60 68 88 96 96 126 168 199
search result:1
copy result:
9 10 11 11 11 19 21 36 60 68 88 96 96 126 168 199 0 0 0 0
STL test project!
这里仍然提醒注意的是,新标准在快速迭代,要注意更新标准的知识。
1、c++标准库不是万能的,有些库其实并不多受欢迎,比如标准输入输出的流操作。
2、c++标准库使用不复杂,但内部机制越来越复杂,特别模板机制,本身就是一个复杂而又困难的事情。而新标准中增加的协程等更是提高了内部实现的复杂度。
3、c++标准从c++11迭代的速度明显加快,要注意新版本的更新和跟进。
在STL的学习过程中,会把相关的源码解析也会展开一部分,这样,既可以更好的了解库的内部实现,又容易理解库的应用情况。STL是学c++的人绕不过去的库,不想用,不代表不需要。