1.空间的配置与释放
对象构造前的空间配置和对象析构后的空间释放,由
第一级配置器中的allocate()直接调用malloc(),deallocate()直接调用free(), reallocate()直接调用realloc()来申请和回收空间
第二级别的做法是,如果区域足够大(超过128bytes时),就交由第一级别配置器处理,否则以内存池管理:每次配置一大块内存,并维护对应的自由链表(free-list)。下次如果有相同大小的内存需求,就直接从free-lists中取,如果释放,就由配置器回收到free-list中,free-list中的块的大小通常为8的倍数。但维护不同指向多个链表的指针也会浪费空间。
第二级的allocate函数做法:如果申请的空间大于128bytes,那么直接调用第一级配置器,小于128bytes就检查对应的free list,如果free list中有,直接分配;否则调用refill()函数;deallocate的做法:该函数首先判断区块大小,大于128bytes就调用第一级配置器,否则找到对应的free list,然后将区块收回。
refill()函数通过调用chunk_alloc()从内存池中获取一块空间(内存池如何管理/)
2.vector
vector中有三个重要的迭代器:start, finish, end_of_storage
start:表示目前使用空间的头
finish:表示目前使用空间的尾
end_of_storage:表示目前可用空间的尾
其中的很多操作如begin(), end(), size(), capacity(), empty(), operator[]等都是通过这三个指针来操作
事实上:迭代器就是普通的指针 vector
vector的内部就是数组,初始化时,会分配一个默认大小的capacity,但push_back()向vector中插入元素时,如果当时的容量不够,那么容量会扩充至两倍。容量的扩充过程中,可能需要重新分配一块更大的空间,元素移动,并释放原来的空间。
vector缺省使用alloc作为分配器。
注意:对vector的任意操作,如果引起空间的重新配置,那么指向原来vector的迭代器就会失效,务必注意。
3.关联容器
所谓关联容器,就是每个数据元素是key+value,当元素插入到关联容器时,根据key,以某种特定规则将元素放置于适当位置,关联容器没有所谓的头尾,不能进行push_back(), push_front(), pop_back(), pop_front()等操作
通常关联容器的内部结构是一个balanced binary tree(平衡二叉树),为的是高效率的操作(lgN),平衡二叉树有很多种:AVL-tree、RB-tree等,STL中的map, set, multimap, multiset内部采用RB-tree实现。
值得注意的是:我们在讨论红黑树之前,首先要记住:红黑树是一个二叉查找树,具备二叉查找树的所有性质
除了二叉查找树的性质,红黑树还有的五个基本性质:
当在对红黑树进行插入和删除等操作时,对树做了修改可能会破坏红黑树的性质。为了继续保持红黑树的性质,可以通过对结点进行重新着色,以及对树进行相关的旋转操作,即通过修改树中某些结点的颜色及指针结构,来达到对红黑树进行插入或删除结点等操作后继续保持它的性质或平衡的目的。
红黑树的调整的大致思想分两步:
iterator begin() {
return (link_type)(*node).next;
}
iterator end() {
return node;
}
list 缺省使用alloc作为空间配置器,并据此另外定义一个list_node_allocator,为的是方便地以节点大小为配置单位。
deque是一种双向开口的连续线性空间,即可以在头尾两端分别做元素的插入和删除操作。vector虽然也可以进行pop_front, push_front,但是其效率非常低。
vector与deque的差别:1.deque允许o(1)时间对头进行插入和移除;2.deque没有所谓容量(capacity)观念,因为它是动态地以分段连续空间组合而成,随时可以增加一些新的空间并链接起来。
deque由一段一段的定量连续空间构成,一旦有必要在deque的前端或尾端增加新空间、便配置一段定量连续空间,串接在整个deque的头端或尾端。