C++标准库1(侯捷)

246 阅读5分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

C++标准库不同于C语言的库,它不是一个个独立的函数,他主要分为6个part(部件),部件之间有紧密的关系存在

C++ Standard Library vs. Standard Template Library

C++标准库=STL(六大部件)+一些小功能

STL六大部件

STL六大部件的关系

复杂度,Complexity,Big-oh

“前闭后开”区间

range-based for statement(since C++11)

auto keyword(since C++11)

容器-结构与分类

unordered containers是C++11才新出现的容器,其实之前也有前身,不过就是一种关联式容器,它底部就是用hash table做的

红色圈起来的就是C++11增加的

List是个双向环状链表,不过环状只是为了实作上的便利性,在使用和功能上只要知道是双向就可以

对于要大量查找的,关联式容器更好,从图上看起来它内部是用树(二分树)做的,事实上是红黑树做的,是一种特殊的二分树,叫高度平衡二分树,就是左边跟右边会自己调整,调整到差不多一样,在查找的时候就不会有最坏的情况,找到某一只很长的右臂。标准库没有规定set和map应该用什么来实现,但由于红黑树很好,所以各个编译器带的标准库都用红黑树来做

mutil表示元素可以重复

hash table有很多做法,但是被公认的最好的,也是所有C++标准库实作都采用的就是hash table里的separate chaining,不过如果碰撞的太多,链表太长,查找是很慢的,所以就有一些法则,如果太长的话就会重新把他打散

以下测试程序之辅助函数

使用容器

使用容器array

使用容器vector

许多容器都有push_back函数

vector不能从前面放,不然要把后面所有元素往后推,例如这个例子就会有100万次构造和析构函数

vector大小的增长是翻倍增长的,例如1,2,4,8,16

.size()获取有多少元素,.capacity()获取容量有多大

这里使用了异常捕获,如果内存不够,要absort()退出程序

使用容器list

max_size这个函数要第二讲第三讲看源码讲

这里用的sort函数不是stl的,而是list容器的,当容器有自带的sort时,一定比stl的快,至于原因,之后了解源代码才能讲清楚

使用容器forward_list

使用容器slist

与forward_list一模一样,不过是早就存在的

使用容器deque

他其实是一段一段的,每个buffer能放许多元素,deque是分段连续的,deque号称是连续的,其实段与段之间是不连续的,是假象,怎么做到的将在第二讲第三讲说

每次扩充一个buffer

使用容器stack

由于stack和queue没有自己的数据结构,是借用deque,所以很多人从技术上不把他们叫做容器,把他们叫做容器的adapter

stack和queue的特性使得他们没有iterator,不然就会破坏先进先出或者先进后出的特性,所以没有find

使用容器queue

使用容器mutilset

使用容器mutilmap

使用容器unordered_mutilset

可以查看有多少篮子,每个篮子有多少元素

篮子数一定比元素数多,这是内部的考量,在第二讲提到,一个观念是,每个篮子链表不能太长,虽然能很快找到篮子,但是篮子是循序查找很慢,长是经验上的,如果元素个数大于等于篮子,篮子就要重新扩充,变成大约两倍那么多

使用容器unordered_mutilmap

使用容器set

使用容器map

key不能重复,但是这里key都不一样,所以有一百万个元素

map能用[]取值赋值,mutimap不可以(可能是因为有重复的可能)

使用容器unordered_set

使用容器unordered_map

还有一些容器如:heap(不是内存的heap),和priority queue,但这些用的人少,而且底部是用其他容器做的支撑,所以就没有写测试程序

使用容器hash_set, hash_map, hash_multiset, hash_multimap

这就是之前muti那些,只不过改了名字,之前是非正式的,是编译器做的,现在是标准库给的,不过现在也可以用,只不过头文件要注意,例如slist就是这样的,头文件是#include<ext/slist>

使用分配器allocator

分配器除了默认的,还有自己写的,那么标准库还有没有提供其他分配器是我们现在要讨论的重点

下面我们只讲gnc所附的分配器

首先使用的容器到底是什么分配器

有没有可能直接使用分配器,可以,因为它就是一个class,就提供两个函数,allocate和deallocate,一个拿,一个还,不过没有需要,因为真正的工具是容器,实在没有必须用背后的分配器拿内存还内存,不过还是试一次

里面的1就是要一个元素,也就是一个int

这里说了怎么用,但不建议用,直接用容器就好,或者用malloc搭配free和new搭配delete,因为这两个消除内存的时候不需要记住几个

对于分配器,谁是最有效率的,谁有什么特性,第二讲会提一些,但最详细的部分在内存管理看