目录
1.避免使用vector<bool>
https://blog.csdn.net/haolexiao/article/details/56837445
2.在函数中定义局部函数:
https://blog.csdn.net/kof2001kop/article/details/7425186
3.malloc、linux、mmap实现
STL学习
1.string 使用
https://blog.csdn.net/qq_42659468/article/details/90381985
2.allocator:
默认是std:allocator,其他用pool_alloc比较多
3.stl库主要是用gp(generic programming)泛型编程实现的,gp是将datas和methods分开;oop是将datas和methods合并起来。
4.
5.operator new()和malloc()
c++中的new会调用operator new(),operator new()中会调用malloc()。c++ malloc内存的结构如下,需要用的部分越大,额外消耗占比越小
stl中的分配器分配内存(allocate)是调用的是operator new(),释放内存(deallocate)用的是operator delete()
GC2.9用的是alloc,没有用allocator。具体结构如下:
目的是为了减少额外的消耗(cookie),建立16条链表,第一个表示8个字节大小的对象,第二个表示16个字节大小的元素,容器需要的元素会缩放到8的倍数,比如50会扩展成56.
cookie上下都有,共8个字节。
6.list:是一个双向列表,一个list有一个node,node是一个list_node指针,因此一个list的对象大小是4(在gc2.9中);在4.9中,一个list有两个指针。一个list_node有两个指针和一个data.
list的iterator类对++(++i,i++),--(--i,i--)等操作符做重载。operator ++(int)是重载后置++,operator ++()是重载前置++。每个iterator有五个结构
iterator_category:iterator的分类性质
difference_type:iterator之间的距离
value_type:iterator存储的对象类型
reference:标准库中没用过
pointer:标准库中没用过
和 array、vector 这些容器迭代器的实现方式不同,由于 list 容器的元素并不是连续存储的,所以该容器迭代器中,必须包含一个可以指向 list 容器的指针,并且该指针还可以借助重载的 *、++、--、==、!= 等运算符,实现迭代器正确的递增、递减、取值等操作。
迭代器的移动就是通过操作节点的指针实现的
一个list:包含一个直接链表的头节点指针,该节点不存放数据。
list 容器实际上就是一个带有头节点的双向循环链表。下图为存有 2 个元素的 list 容器:
迭代器是一个模板类
http://c.biancheng.net/view/6955.html
7.Vector
扩充需要重新分配内存,两倍增长
一个vector对象有三个指针
两倍增长,先看初始大小是不是0,分配新空间,拷贝旧内容,插入新内容,插入安插点后的内容
迭代器,只需要一个指针
一个vector对象有三个指针:_Myfirst 指向的是 vector 容器对象的起始字节位置;_Mylast 指向当前最后一个元素的末尾字节;_myend 指向整个 vector 容器所占用内存空间的末尾字节。
在此基础上,将 3 个迭代器两两结合,还可以表达不同的含义,例如:
- _Myfirst 和 _Mylast 可以用来表示 vector 容器中目前已被使用的内存空间;
- _Mylast 和 _Myend 可以用来表示 vector 容器目前空闲的内存空间;
- _Myfirst 和 _Myend 可以用表示 vector 容器的容量
迭代器是元素类型的指针
http://c.biancheng.net/view/6901.html
8.Array
就是个数组
Array要指定类型和大小,大小不为0,至少为1。是连续空间。迭代器就是个指针
9.Forward list 和list区别就是只有单向的
10.Deque
双向开口,分段串接起来,即分段连续
里面有个vector,每个元素是指针,指向一个组。
迭代器是一个class,有四个指针。cur是当前,first和last是元组的边界,node指向vector当前元组的位置。
一个deque对象有两个迭代器,一个map指针,一个size。默认一个元组存储512字节/元素大小。
操作符重载:后++调用前++
重载++ += -- 等操作符使得看起来连续
Vector扩充时复制到新内存的中间
Queue和stack都是基于deque实现,两个都不允许遍历,不提供iterator,因为要保证先进先出或者先进后出。两个都还可以使用list作为底层实现。stack可以用vector作为底层实现,queue不可以。两个都不可以用set和map作为底层实现
deque:deque
容器存储数据的空间是由一段一段等长的连续空间构成,各段空间之间并不一定是连续的,可以位于在内存的不同区域
为了管理这些连续空间,deque 容器用数组(数组名假设为 map)存储着各个连续空间的首地址。也就是说,map 数组中存储的都是指针,指向那些真正用来存储数据的各个连续空间(如图 1 所示)。
通过建立 map 数组,deque 容器申请的这些分段的连续空间就能实现“整体连续”的效果。换句话说,当 deque 容器需要在头部或尾部增加存储空间时,它会申请一段新的连续空间,同时在 map 数组的开头或结尾添加指向该空间的指针,由此该空间就串接到了 deque 容器的头部或尾部。
迭代器是一个类,迭代器内部包含 4 个指针,它们各自的作用为:
- cur:指向当前正在遍历的元素;
- first:指向当前连续空间的首地址;
- last:指向当前连续空间的末尾地址;
- node:它是一个二级指针,用于指向 map 数组中存储的指向当前连续空间的指针。
一个deque有两个迭代器,分别是start和finish,还有一个数组指针,指向中控器map数组。start 迭代器记录着 map 数组中首个连续空间的信息,finish 迭代器记录着 map 数组中最后一个连续空间的信息。另外需要注意的是,和普通 deque 迭代器不同,start 迭代器中的 cur 指针指向的是连续空间中首个元素;而 finish 迭代器中的 cur 指针指向的是连续空间最后一个元素的下一个位置。
http://c.biancheng.net/view/6908.html
11.红黑树
提供迭代器,可以++和--,但不应用迭代器改变元素的值
有五个模板参数,key data 合成value,keyofvalue怎么从value去除key.compare怎么比较两个key的大小。第五个是分配器
一个rbtree有一个节点数量,一个头节点指针,一个compare函数,仿函数大小为1。共9,补充到12
Insert有insert unique和insert equal
12.set multiset
可以用迭代器遍历,但是不能通过迭代器修改。通过返回const iterator保证
Map multimap的iterator也一样,map用insert unique,multimap用insert equal
13.Map multimap
迭代器是用红黑树的迭代器,没有用const,而是在pair中将第一个设置为const。
[]重载较特殊,要让不存在的查询值返回默认值
14.Hashtable
用哈希函数选定key的位置
哈希碰撞,设计新的哈希函数,或者使用链表接起来
用链表到某个链表过长,如果元素个数比bucket个数要多,就要增加bucket的个数,重新hash.bucket的个数一般都是素数。
hashtable底层结构:
hashFcn:怎么计算出hashcode,即要放到哪个bucket
extractkey:怎么从pair里提取出key
equalkey:怎么判断两个key相等
迭代器是一个类