STL源代码剖析 容器 stl_deque.h
本文为senlie原创。转载请保留此地址:http://blog.csdn.net/zhengsenlie
deque
------------------------------------------------------------------------
??一直看不懂 operator->() 。不明确它为什么不用接受參数。直接 return &(operator*())
好像我们用迭代器的时候也不没怎么用到这个函数,甚至我都不会用
1.概述
vector 是单向开口的连续线性空间。deque 则是一种双向开口的连续线性空间
同意常数时间内对起头端进行元素的插入和移除操作
没有容量概念。由于它是动态地以分段连续空间组合而成,随时能够添加一段新的空间并链接起来
deque 的迭代器不是普通指针,如非必要。应选择 vector 而非 deque
对deque 排序,可将 deque 先完整拷贝到一个 vector 身上,将 vector 排序后,再复制回 deque
图 4-9
2.deque 的中控器
map (不是 STL 里的 map 容器) --> 主控,是一小块连续空间。每一个元素指向还有一段较大的连续空间 node-buffer
node-buffer --> 存储空间主体
图 4-10
3.迭代器
cur --> 指出分段连续空间在哪里
first, last --> 推断自己是否已经处于缓冲区的边缘
node --> 在缓冲区边缘前进或后退时必须知道中控器在哪
图4-11
图4-12
#ifndef __SGI_STL_INTERNAL_DEQUE_H
#define __SGI_STL_INTERNAL_DEQUE_H __STL_BEGIN_NAMESPACE #if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32)
#pragma set woff 1174
#endif // Note: this function is simply a kludge to work around several compilers'
// bugs in handling constant expressions.
// 决定缓冲区大小
// 假设 n 不为 0。传回n ,表示 buffer size 由用户自己定义
// 假设 n 为 0,表示 buffer size 使用默认值,那么
// 假设 sz(元素大小,sizeof(value_type))小于512,返回 512/sz,
// 假设 sz不小于 512。返回 1
inline size_t __deque_buf_size(size_t n, size_t sz)
{
return n != 0 ? n : (sz < 512 ? size_t(512 / sz) : size_t(1));
} #ifndef __STL_NON_TYPE_TMPL_PARAM_BUG
template <class T, class Ref, class Ptr, size_t BufSiz>
struct __deque_iterator {
typedef __deque_iterator<T, T&, T*, BufSiz> iterator;
typedef __deque_iterator<T, const T&, const T*, BufSiz> const_iterator;
static size_t buffer_size() {return __deque_buf_size(BufSiz, sizeof(T)); }
#else /* __STL_NON_TYPE_TMPL_PARAM_BUG */
template <class T, class Ref, class Ptr>
struct __deque_iterator {
typedef __deque_iterator<T, T&, T*> iterator;
typedef __deque_iterator<T, const T&, const T*> const_iterator;
static size_t buffer_size() {return __deque_buf_size(0, sizeof(T)); }
#endif typedef random_access_iterator_tag iterator_category;
typedef T value_type;
typedef Ptr pointer;
typedef Ref reference;
typedef size_t size_type;
typedef ptrdiff_t difference_type;
typedef T** map_pointer; typedef __deque_iterator self; T* cur; //指向缓冲区的现行元素
T* first; //指向缓冲区的头
T* last; // 指向缓冲区的尾 map_pointer node; //指向中控器 __deque_iterator(T* x, map_pointer y)
: cur(x), first(*y), last(*y + buffer_size()), node(y) {}
__deque_iterator() : cur(0), first(0), last(0), node(0) {}
__deque_iterator(const iterator& x)
: cur(x.cur), first(x.first), last(x.last), node(x.node) {}
//解引用
reference operator*() const { return *cur; }
#ifndef __SGI_STL_NO_ARROW_OPERATOR
//??好像没用过这东西
pointer operator->() const { return &(operator*()); }
#endif /* __SGI_STL_NO_ARROW_OPERATOR */
//两个迭代器之间的距离
difference_type operator-(const self& x) const {
return difference_type(buffer_size()) * (node - x.node - 1) +
(cur - first) + (x.last - x.cur);
}
//前置++
self& operator++() {
++cur; //切换至下一个元素
if (cur == last) { //假设已达到所在缓冲区的尾端
set_node(node + 1); //就切换至下一缓冲区的第一个元素
cur = first;
}
return *this;
}
//后置++
self operator++(int) {
self tmp = *this;
++*this; //调用前置++ 完毕前进 ? --> yes
return tmp;
}
//前置--
self& operator--() {
if (cur == first) {
set_node(node - 1);
cur = last;
}
--cur;
return *this;
}
//后置--
self operator--(int) {
self tmp = *this;
--*this;
return tmp;
}
//随机存取
self& operator+=(difference_type n) {
difference_type offset = n + (cur - first);
//目标位置在同一缓冲区
if (offset >= 0 && offset < difference_type(buffer_size()))
cur += n;
//目标位置在不同缓冲区
else {
difference_type node_offset =
offset > 0 ? offset / difference_type(buffer_size())
: -difference_type((-offset - 1) / buffer_size()) - 1;
//切换至正确的节点(缓冲区)
set_node(node + node_offset);
//切换至正确的元素
cur = first + (offset - node_offset * difference_type(buffer_size()));
}
return *this;
} self operator+(difference_type n) const {
self tmp = *this;
return tmp += n; //? 不懂为什么是对 暂时变量 调用 operator+= --> 由于是 operator+,本来就不用改变 this 指向的对象
} self& operator-=(difference_type n) { return *this += -n; } self operator-(difference_type n) const {
self tmp = *this;
return tmp -= n;
} reference operator[](difference_type n) const { return *(*this + n); } bool operator==(const self& x) const { return cur == x.cur; }
bool operator!=(const self& x) const { return !(*this == x); }
bool operator<(const self& x) const {
return (node == x.node) ? (cur < x.cur) : (node < x.node);
}
//使用 set_node 来跳一个缓冲区
void set_node(map_pointer new_node) {
node = new_node;
first = *new_node;
last = first + difference_type(buffer_size());
}
}; #ifndef __STL_CLASS_PARTIAL_SPECIALIZATION #ifndef __STL_NON_TYPE_TMPL_PARAM_BUG template <class T, class Ref, class Ptr, size_t BufSiz>
inline random_access_iterator_tag
iterator_category(const __deque_iterator<T, Ref, Ptr, BufSiz>&) {
return random_access_iterator_tag();
} template <class T, class Ref, class Ptr, size_t BufSiz>
inline T* value_type(const __deque_iterator<T, Ref, Ptr, BufSiz>&) {
return 0;
} template <class T, class Ref, class Ptr, size_t BufSiz>
inline ptrdiff_t* distance_type(const __deque_iterator<T, Ref, Ptr, BufSiz>&) {
return 0;
} #else /* __STL_NON_TYPE_TMPL_PARAM_BUG */ template <class T, class Ref, class Ptr>
inline random_access_iterator_tag
iterator_category(const __deque_iterator<T, Ref, Ptr>&) {
return random_access_iterator_tag();
} template <class T, class Ref, class Ptr>
inline T* value_type(const __deque_iterator<T, Ref, Ptr>&) { return 0; } template <class T, class Ref, class Ptr>
inline ptrdiff_t* distance_type(const __deque_iterator<T, Ref, Ptr>&) {
return 0;
} #endif /* __STL_NON_TYPE_TMPL_PARAM_BUG */ #endif /* __STL_CLASS_PARTIAL_SPECIALIZATION */ // See __deque_buf_size(). The only reason that the default value is 0
// is as a workaround for bugs in the way that some compilers handle
// constant expressions. // deque 类
template <class T, class Alloc = alloc, size_t BufSiz = 0>
class deque {
public: // Basic types
typedef T value_type;
typedef value_type* pointer;
typedef const value_type* const_pointer;
typedef value_type& reference;
typedef const value_type& const_reference;
typedef size_t size_type;
typedef ptrdiff_t difference_type; public: // Iterators
#ifndef __STL_NON_TYPE_TMPL_PARAM_BUG
typedef __deque_iterator<T, T&, T*, BufSiz> iterator;
typedef __deque_iterator<T, const T&, const T&, BufSiz> const_iterator;
#else /* __STL_NON_TYPE_TMPL_PARAM_BUG */
typedef __deque_iterator<T, T&, T*> iterator;
typedef __deque_iterator<T, const T&, const T*> const_iterator;
#endif /* __STL_NON_TYPE_TMPL_PARAM_BUG */ #ifdef __STL_CLASS_PARTIAL_SPECIALIZATION
typedef reverse_iterator<const_iterator> const_reverse_iterator;
typedef reverse_iterator<iterator> reverse_iterator;
#else /* __STL_CLASS_PARTIAL_SPECIALIZATION */
typedef reverse_iterator<const_iterator, value_type, const_reference,
difference_type>
const_reverse_iterator;
typedef reverse_iterator<iterator, value_type, reference, difference_type>
reverse_iterator;
#endif /* __STL_CLASS_PARTIAL_SPECIALIZATION */ protected: // Internal typedefs
//元素指针的指针,即指向 map 中元素的指针
typedef pointer* map_pointer;
//空间配置器。每次配置一个元素大小
typedef simple_alloc<value_type, Alloc> data_allocator;
//空间配置器,每次配置一个指针大小
typedef simple_alloc<pointer, Alloc> map_allocator; static size_type buffer_size() {
return __deque_buf_size(BufSiz, sizeof(value_type));
}
static size_type initial_map_size() { return 8; } protected: // Data members
iterator start; //第一缓冲区的第一个元素
iterator finish; //最后缓冲区的最后一个元素 map_pointer map; //指向 map
size_type map_size; // map 内可容纳多少指针 public: // Basic accessors
iterator begin() { return start; }
iterator end() { return finish; }
const_iterator begin() const { return start; }
const_iterator end() const { return finish; } reverse_iterator rbegin() { return reverse_iterator(finish); }
reverse_iterator rend() { return reverse_iterator(start); }
const_reverse_iterator rbegin() const {
return const_reverse_iterator(finish);
}
const_reverse_iterator rend() const {
return const_reverse_iterator(start);
} reference operator[](size_type n) { return start[difference_type(n)]; }
const_reference operator[](size_type n) const {
return start[difference_type(n)];
} reference front() { return *start; }
reference back() {
//? 下面三行为什么不改为: return *(finish - 1);
iterator tmp = finish;
--tmp;
return *tmp;
}
const_reference front() const { return *start; }
const_reference back() const {
const_iterator tmp = finish;
--tmp;
return *tmp;
} size_type size() const { return finish - start;; }
size_type max_size() const { return size_type(-1); }
bool empty() const { return finish == start; } public: // Constructor, destructor.
deque()
: start(), finish(), map(0), map_size(0)
{
create_map_and_nodes(0);
} deque(const deque& x)
: start(), finish(), map(0), map_size(0)
{
create_map_and_nodes(x.size());
__STL_TRY {
uninitialized_copy(x.begin(), x.end(), start);
}
__STL_UNWIND(destroy_map_and_nodes());
} deque(size_type n, const value_type& value)
: start(), finish(), map(0), map_size(0)
{
fill_initialize(n, value);
} deque(int n, const value_type& value)
: start(), finish(), map(0), map_size(0)
{
fill_initialize(n, value);
} deque(long n, const value_type& value)
: start(), finish(), map(0), map_size(0)
{
fill_initialize(n, value);
} explicit deque(size_type n)
: start(), finish(), map(0), map_size(0)
{
fill_initialize(n, value_type());
} #ifdef __STL_MEMBER_TEMPLATES template <class InputIterator>
deque(InputIterator first, InputIterator last)
: start(), finish(), map(0), map_size(0)
{
range_initialize(first, last, iterator_category(first));
} #else /* __STL_MEMBER_TEMPLATES */ deque(const value_type* first, const value_type* last)
: start(), finish(), map(0), map_size(0)
{
create_map_and_nodes(last - first);
__STL_TRY {
uninitialized_copy(first, last, start);
}
__STL_UNWIND(destroy_map_and_nodes());
} deque(const_iterator first, const_iterator last)
: start(), finish(), map(0), map_size(0)
{
create_map_and_nodes(last - first);
__STL_TRY {
uninitialized_copy(first, last, start);
}
__STL_UNWIND(destroy_map_and_nodes());
} #endif /* __STL_MEMBER_TEMPLATES */ ~deque() {
destroy(start, finish);
destroy_map_and_nodes();
} deque& operator= (const deque& x) {
const size_type len = size();
if (&x != this) {
if (len >= x.size())
erase(copy(x.begin(), x.end(), start), finish);
else {
const_iterator mid = x.begin() + difference_type(len);
copy(x.begin(), mid, start);
insert(finish, mid, x.end());
}
}
return *this;
} void swap(deque& x) {
__STD::swap(start, x.start);
__STD::swap(finish, x.finish);
__STD::swap(map, x.map);
__STD::swap(map_size, x.map_size);
} public: // push_* and pop_* void push_back(const value_type& t) {
//最后缓冲区尚有一个以上的备用空间
if (finish.cur != finish.last - 1) {
construct(finish.cur, t);
++finish.cur;
}
//仅仅剩一个备用空间
else
push_back_aux(t);
} void push_front(const value_type& t) {
//第一缓冲区尚有备用空间
if (start.cur != start.first) {
construct(start.cur - 1, t);
--start.cur;
}
//尚有备用空间
else
push_front_aux(t);
} void pop_back() {
//最后缓冲区有一个或很多其它的元素
if (finish.cur != finish.first) {
--finish.cur; //指针前移。相当于排除了最后的元素
destroy(finish.cur); //析构并释放最后的元素
}
//最后缓冲区没有不论什么元素
else
pop_back_aux();
} void pop_front() {
//第一缓冲区有一个或很多其它个元素
if (start.cur != start.last - 1) {
destroy(start.cur);
++start.cur;
}
//第一缓冲区且有一个元素
else
pop_front_aux();
} public: // Insert iterator insert(iterator position, const value_type& x) {
//假设插入点是 deque 最前端,交给 push_front 去做
if (position.cur == start.cur) {
push_front(x);
return start;
}
//假设插入点是 deque 最后端,交给 push_back 去做
else if (position.cur == finish.cur) {
push_back(x);
iterator tmp = finish;
--tmp;
return tmp;
}
//其它情况交给 insert_aux 去做
else {
return insert_aux(position, x);
}
} iterator insert(iterator position) { return insert(position, value_type()); } void insert(iterator pos, size_type n, const value_type& x); void insert(iterator pos, int n, const value_type& x) {
insert(pos, (size_type) n, x);
}
void insert(iterator pos, long n, const value_type& x) {
insert(pos, (size_type) n, x);
} #ifdef __STL_MEMBER_TEMPLATES template <class InputIterator>
void insert(iterator pos, InputIterator first, InputIterator last) {
insert(pos, first, last, iterator_category(first));
} #else /* __STL_MEMBER_TEMPLATES */ void insert(iterator pos, const value_type* first, const value_type* last);
void insert(iterator pos, const_iterator first, const_iterator last); #endif /* __STL_MEMBER_TEMPLATES */ void resize(size_type new_size, const value_type& x) {
const size_type len = size();
if (new_size < len)
erase(start + new_size, finish);
else
insert(finish, new_size - len, x);
} void resize(size_type new_size) { resize(new_size, value_type()); } public: // Erase
//清除 pos 所指的元素
iterator erase(iterator pos) {
iterator next = pos;
++next;
difference_type index = pos - start; // 清除点前的元素个数
if (index < (size() >> 1)) { // 假设清除点之前的元素比較少,则移动清除点之前的元素
copy_backward(start, pos, next);
pop_front();
}
else { //假设清除点之后的元素比較少,则移动清除点之后的元素
copy(next, finish, pos);
pop_back();
}
return start + index;
} iterator erase(iterator first, iterator last);
void clear(); protected: // Internal construction/destruction void create_map_and_nodes(size_type num_elements);
void destroy_map_and_nodes();
void fill_initialize(size_type n, const value_type& value); #ifdef __STL_MEMBER_TEMPLATES template <class InputIterator>
void range_initialize(InputIterator first, InputIterator last,
input_iterator_tag); template <class ForwardIterator>
void range_initialize(ForwardIterator first, ForwardIterator last,
forward_iterator_tag); #endif /* __STL_MEMBER_TEMPLATES */ protected: // Internal push_* and pop_* void push_back_aux(const value_type& t);
void push_front_aux(const value_type& t);
void pop_back_aux();
void pop_front_aux(); protected: // Internal insert functions #ifdef __STL_MEMBER_TEMPLATES template <class InputIterator>
void insert(iterator pos, InputIterator first, InputIterator last,
input_iterator_tag); template <class ForwardIterator>
void insert(iterator pos, ForwardIterator first, ForwardIterator last,
forward_iterator_tag); #endif /* __STL_MEMBER_TEMPLATES */ iterator insert_aux(iterator pos, const value_type& x);
void insert_aux(iterator pos, size_type n, const value_type& x); #ifdef __STL_MEMBER_TEMPLATES template <class ForwardIterator>
void insert_aux(iterator pos, ForwardIterator first, ForwardIterator last,
size_type n); #else /* __STL_MEMBER_TEMPLATES */ void insert_aux(iterator pos,
const value_type* first, const value_type* last,
size_type n); void insert_aux(iterator pos, const_iterator first, const_iterator last,
size_type n); #endif /* __STL_MEMBER_TEMPLATES */ iterator reserve_elements_at_front(size_type n) {
size_type vacancies = start.cur - start.first;
if (n > vacancies)
new_elements_at_front(n - vacancies);
return start - difference_type(n);
} iterator reserve_elements_at_back(size_type n) {
size_type vacancies = (finish.last - finish.cur) - 1;
if (n > vacancies)
new_elements_at_back(n - vacancies);
return finish + difference_type(n);
} void new_elements_at_front(size_type new_elements);
void new_elements_at_back(size_type new_elements); void destroy_nodes_at_front(iterator before_start);
void destroy_nodes_at_back(iterator after_finish); protected: // Allocation of map and nodes // Makes sure the map has space for new nodes. Does not actually
// add the nodes. Can invalidate map pointers. (And consequently,
// deque iterators.) void reserve_map_at_back (size_type nodes_to_add = 1) {
if (nodes_to_add + 1 > map_size - (finish.node - map))
reallocate_map(nodes_to_add, false);
} void reserve_map_at_front (size_type nodes_to_add = 1) {
if (nodes_to_add > start.node - map)
reallocate_map(nodes_to_add, true);
} void reallocate_map(size_type nodes_to_add, bool add_at_front); pointer allocate_node() { return data_allocator::allocate(buffer_size()); }
void deallocate_node(pointer n) {
data_allocator::deallocate(n, buffer_size());
} #ifdef __STL_NON_TYPE_TMPL_PARAM_BUG
public:
bool operator==(const deque<T, Alloc, 0>& x) const {
return size() == x.size() && equal(begin(), end(), x.begin());
}
bool operator!=(const deque<T, Alloc, 0>& x) const {
return size() != x.size() || !equal(begin(), end(), x.begin());
}
bool operator<(const deque<T, Alloc, 0>& x) const {
return lexicographical_compare(begin(), end(), x.begin(), x.end());
}
#endif /* __STL_NON_TYPE_TMPL_PARAM_BUG */
}; // Non-inline member functions template <class T, class Alloc, size_t BufSize>
void deque<T, Alloc, BufSize>::insert(iterator pos,
size_type n, const value_type& x) {
if (pos.cur == start.cur) {
iterator new_start = reserve_elements_at_front(n);
uninitialized_fill(new_start, start, x);
start = new_start;
}
else if (pos.cur == finish.cur) {
iterator new_finish = reserve_elements_at_back(n);
uninitialized_fill(finish, new_finish, x);
finish = new_finish;
}
else
insert_aux(pos, n, x);
} #ifndef __STL_MEMBER_TEMPLATES template <class T, class Alloc, size_t BufSize>
void deque<T, Alloc, BufSize>::insert(iterator pos,
const value_type* first,
const value_type* last) {
size_type n = last - first;
if (pos.cur == start.cur) {
iterator new_start = reserve_elements_at_front(n);
__STL_TRY {
uninitialized_copy(first, last, new_start);
start = new_start;
}
__STL_UNWIND(destroy_nodes_at_front(new_start));
}
else if (pos.cur == finish.cur) {
iterator new_finish = reserve_elements_at_back(n);
__STL_TRY {
uninitialized_copy(first, last, finish);
finish = new_finish;
}
__STL_UNWIND(destroy_nodes_at_back(new_finish));
}
else
insert_aux(pos, first, last, n);
} template <class T, class Alloc, size_t BufSize>
void deque<T, Alloc, BufSize>::insert(iterator pos,
const_iterator first,
const_iterator last)
{
size_type n = last - first;
if (pos.cur == start.cur) {
iterator new_start = reserve_elements_at_front(n);
__STL_TRY {
uninitialized_copy(first, last, new_start);
start = new_start;
}
__STL_UNWIND(destroy_nodes_at_front(new_start));
}
else if (pos.cur == finish.cur) {
iterator new_finish = reserve_elements_at_back(n);
__STL_TRY {
uninitialized_copy(first, last, finish);
finish = new_finish;
}
__STL_UNWIND(destroy_nodes_at_back(new_finish));
}
else
insert_aux(pos, first, last, n);
} #endif /* __STL_MEMBER_TEMPLATES */ template <class T, class Alloc, size_t BufSize>
deque<T, Alloc, BufSize>::iterator
//清除[first, last)区间内的全部元素
deque<T, Alloc, BufSize>::erase(iterator first, iterator last) {
//假设清除区间就是整个 deque ,直接调用 clear() 就可以
if (first == start && last == finish) {
clear();
return finish;
}
else {
difference_type n = last - first;
difference_type elems_before = first - start;
//假设清除区间前面的元素较少,向后移动前方元素(覆盖清除区间)。然后析构冗余元素
if (elems_before < (size() - n) / 2) {
copy_backward(start, first, last);
iterator new_start = start + n;
destroy(start, new_start);
for (map_pointer cur = start.node; cur < new_start.node; ++cur)
data_allocator::deallocate(*cur, buffer_size());
start = new_start;
}
//假设清除区间后面的元素较少。向前移动后方元素,然后析构冗余元素
else {
copy(last, finish, first);
iterator new_finish = finish - n;
destroy(new_finish, finish);
for (map_pointer cur = new_finish.node + 1; cur <= finish.node; ++cur)
data_allocator::deallocate(*cur, buffer_size());
finish = new_finish;
}
return start + elems_before;
}
} //清除整个 deque ,须要保有一个缓冲区。 template <class T, class Alloc, size_t BufSize>
void deque<T, Alloc, BufSize>::clear() {
//针对头尾以外的每一个缓冲区。析构全部元素并释放缓冲区空间
for (map_pointer node = start.node + 1; node < finish.node; ++node) {
destroy(*node, *node + buffer_size());
data_allocator::deallocate(*node, buffer_size());
}
//还剩头尾两个缓冲区
if (start.node != finish.node) {
destroy(start.cur, start.last);
destroy(finish.first, finish.cur);
//仅仅释放尾部缓冲区的空间,保留头缓冲区
data_allocator::deallocate(finish.first, buffer_size());
}
//仅仅剩一个缓冲区
else
//不释放唯一的缓冲区空间
destroy(start.cur, finish.cur); finish = start;
}
//产生并安排好 deque 的结构
template <class T, class Alloc, size_t BufSize>
void deque<T, Alloc, BufSize>::create_map_and_nodes(size_type num_elements) {
//须要的节点数 = (元素个数/每一个缓冲区可容纳的元素个数) + 1
//假设刚好整除。会多配一个节点
size_type num_nodes = num_elements / buffer_size() + 1;
// initial_map_size 函数返回 8 ,所以这里是取 8 和 "所需节点数加2(前后预留一个。扩充时可用)" 的最大值
map_size = max(initial_map_size(), num_nodes + 2);
//配置出一个"具有 map_size 个节点"的 map
map = map_allocator::allocate(map_size); //令 nstart 和 nfinish 指向 map 所拥有之全部节点的最中央区段
map_pointer nstart = map + (map_size - num_nodes) / 2;
map_pointer nfinish = nstart + num_nodes - 1; map_pointer cur;
__STL_TRY {
//为 map 内的每一个现用节点配置缓冲区。 全部缓冲区加起来就是 deque 的可用空间(最后一个缓冲区可能留有一些余裕)
for (cur = nstart; cur <= nfinish; ++cur)
*cur = allocate_node();
}
# ifdef __STL_USE_EXCEPTIONS
catch(...) {
for (map_pointer n = nstart; n < cur; ++n)
deallocate_node(*n);
map_allocator::deallocate(map, map_size);
throw;
}
# endif /* __STL_USE_EXCEPTIONS */
//为 deque 内的两个迭代器 start 和 end 设定正确内容
start.set_node(nstart);
finish.set_node(nfinish);
start.cur = start.first;
finish.cur = finish.first + num_elements % buffer_size();
} // This is only used as a cleanup function in catch clauses.
template <class T, class Alloc, size_t BufSize>
void deque<T, Alloc, BufSize>::destroy_map_and_nodes() {
for (map_pointer cur = start.node; cur <= finish.node; ++cur)
deallocate_node(*cur);
map_allocator::deallocate(map, map_size);
} //负责产生并安排好 deque 的结构,并元素的初值设定妥当
template <class T, class Alloc, size_t BufSize>
void deque<T, Alloc, BufSize>::fill_initialize(size_type n,
const value_type& value) {
create_map_and_nodes(n);//把 deque 的结构都产生并安排好
map_pointer cur;
__STL_TRY {
//为每一个节点的缓冲区设定初值
for (cur = start.node; cur < finish.node; ++cur)
uninitialized_fill(*cur, *cur + buffer_size(), value);
//最后一个节点的设定稍有不同(由于尾端可能有备用空间。不必设初值)
uninitialized_fill(finish.first, finish.cur, value);
}
# ifdef __STL_USE_EXCEPTIONS
catch(...) {
for (map_pointer n = start.node; n < cur; ++n)
destroy(*n, *n + buffer_size());
destroy_map_and_nodes();
throw;
}
# endif /* __STL_USE_EXCEPTIONS */
} #ifdef __STL_MEMBER_TEMPLATES template <class T, class Alloc, size_t BufSize>
template <class InputIterator>
void deque<T, Alloc, BufSize>::range_initialize(InputIterator first,
InputIterator last,
input_iterator_tag) {
create_map_and_nodes(0);
for ( ; first != last; ++first)
push_back(*first);
} template <class T, class Alloc, size_t BufSize>
template <class ForwardIterator>
void deque<T, Alloc, BufSize>::range_initialize(ForwardIterator first,
ForwardIterator last,
forward_iterator_tag) {
size_type n = 0;
distance(first, last, n);
create_map_and_nodes(n);
__STL_TRY {
uninitialized_copy(first, last, start);
}
__STL_UNWIND(destroy_map_and_nodes());
} #endif /* __STL_MEMBER_TEMPLATES */ // 仅仅有当 finish.cur == finish.last - 1 时才会调用,即仅仅剩一个备用空间
template <class T, class Alloc, size_t BufSize>
void deque<T, Alloc, BufSize>::push_back_aux(const value_type& t) {
value_type t_copy = t;
reserve_map_at_back();
//配置一个新缓冲区
*(finish.node + 1) = allocate_node();
__STL_TRY {
construct(finish.cur, t_copy); //设置元素值
finish.set_node(finish.node + 1); //改变 finish, 令其指向新节点
finish.cur = finish.first; //设定 finish 的状态
}
__STL_UNWIND(deallocate_node(*(finish.node + 1)));
} // 仅仅有当 start.cur == start.first 才会被调用。即第一个缓冲区尚有备用空间可用了
//--> 为什么 push_back 的时候是仅仅有一个备用空间时调用。而 push_front 是没有备用空间时调用 ??
template <class T, class Alloc, size_t BufSize>
void deque<T, Alloc, BufSize>::push_front_aux(const value_type& t) {
value_type t_copy = t;
reserve_map_at_front();
*(start.node - 1) = allocate_node();
__STL_TRY {
start.set_node(start.node - 1);
start.cur = start.last - 1;
construct(start.cur, t_copy);
}
# ifdef __STL_USE_EXCEPTIONS
catch(...) {
start.set_node(start.node + 1);
start.cur = start.first;
deallocate_node(*(start.node - 1));
throw;
}
# endif /* __STL_USE_EXCEPTIONS */
} // 仅仅有当 finish.cur == finish.first 时才会调用
template <class T, class Alloc, size_t BufSize>
void deque<T, Alloc, BufSize>:: pop_back_aux() {
deallocate_node(finish.first); //释放最后一个缓冲区
finish.set_node(finish.node - 1); //调整 finish 的状态,使指向上一个缓冲区的最后一个元素
finish.cur = finish.last - 1;
destroy(finish.cur); //将该元素析构
} //仅仅有当 start.cur == start.last - 1 时才会调用
template <class T, class Alloc, size_t BufSize>
void deque<T, Alloc, BufSize>::pop_front_aux() {
destroy(start.cur); //将第一缓冲区的第一个元素析构
deallocate_node(start.first); //释放第一缓冲区
start.set_node(start.node + 1); //调整 start 的状态,使指向下一个缓冲区的第一个元素
start.cur = start.first;
} #ifdef __STL_MEMBER_TEMPLATES template <class T, class Alloc, size_t BufSize>
template <class InputIterator>
void deque<T, Alloc, BufSize>::insert(iterator pos,
InputIterator first, InputIterator last,
input_iterator_tag) {
copy(first, last, inserter(*this, pos));
} template <class T, class Alloc, size_t BufSize>
template <class ForwardIterator>
void deque<T, Alloc, BufSize>::insert(iterator pos,
ForwardIterator first,
ForwardIterator last,
forward_iterator_tag) {
size_type n = 0;
distance(first, last, n);
if (pos.cur == start.cur) {
iterator new_start = reserve_elements_at_front(n);
__STL_TRY {
uninitialized_copy(first, last, new_start);
start = new_start;
}
__STL_UNWIND(destroy_nodes_at_front(new_start));
}
else if (pos.cur == finish.cur) {
iterator new_finish = reserve_elements_at_back(n);
__STL_TRY {
uninitialized_copy(first, last, finish);
finish = new_finish;
}
__STL_UNWIND(destroy_nodes_at_back(new_finish));
}
else
insert_aux(pos, first, last, n);
} #endif /* __STL_MEMBER_TEMPLATES */ template <class T, class Alloc, size_t BufSize>
typename deque<T, Alloc, BufSize>::iterator
deque<T, Alloc, BufSize>::insert_aux(iterator pos, const value_type& x) {
difference_type index = pos - start;
value_type x_copy = x;
//假设插入点之前的元素个数比較少。在最前端增加与第一个元素同值的元素,然后进行元素移动
if (index < size() / 2) {
push_front(front());
iterator front1 = start;
++front1;
iterator front2 = front1;
++front2;
pos = start + index;
iterator pos1 = pos;
++pos1;
copy(front2, pos1, front1);
} //假设插入点之后的元素个数比較少,在最后端增加与最后一个元素同值的元素。然后进行元素移动
else {
push_back(back());
iterator back1 = finish;
--back1;
iterator back2 = back1;
--back2;
pos = start + index;
copy_backward(pos, back2, back1);
}
//在插入点上设定新值
*pos = x_copy;
return pos;
} template <class T, class Alloc, size_t BufSize>
void deque<T, Alloc, BufSize>::insert_aux(iterator pos,
size_type n, const value_type& x) {
const difference_type elems_before = pos - start;
size_type length = size();
value_type x_copy = x;
if (elems_before < length / 2) {
iterator new_start = reserve_elements_at_front(n);
iterator old_start = start;
pos = start + elems_before;
__STL_TRY {
if (elems_before >= difference_type(n)) {
iterator start_n = start + difference_type(n);
uninitialized_copy(start, start_n, new_start);
start = new_start;
copy(start_n, pos, old_start);
fill(pos - difference_type(n), pos, x_copy);
}
else {
__uninitialized_copy_fill(start, pos, new_start, start, x_copy);
start = new_start;
fill(old_start, pos, x_copy);
}
}
__STL_UNWIND(destroy_nodes_at_front(new_start));
}
else {
iterator new_finish = reserve_elements_at_back(n);
iterator old_finish = finish;
const difference_type elems_after = difference_type(length) - elems_before;
pos = finish - elems_after;
__STL_TRY {
if (elems_after > difference_type(n)) {
iterator finish_n = finish - difference_type(n);
uninitialized_copy(finish_n, finish, finish);
finish = new_finish;
copy_backward(pos, finish_n, old_finish);
fill(pos, pos + difference_type(n), x_copy);
}
else {
__uninitialized_fill_copy(finish, pos + difference_type(n),
x_copy,
pos, finish);
finish = new_finish;
fill(pos, old_finish, x_copy);
}
}
__STL_UNWIND(destroy_nodes_at_back(new_finish));
}
} #ifdef __STL_MEMBER_TEMPLATES template <class T, class Alloc, size_t BufSize>
template <class ForwardIterator>
void deque<T, Alloc, BufSize>::insert_aux(iterator pos,
ForwardIterator first,
ForwardIterator last,
size_type n)
{
const difference_type elems_before = pos - start;
size_type length = size();
if (elems_before < length / 2) {
iterator new_start = reserve_elements_at_front(n);
iterator old_start = start;
pos = start + elems_before;
__STL_TRY {
if (elems_before >= difference_type(n)) {
iterator start_n = start + difference_type(n);
uninitialized_copy(start, start_n, new_start);
start = new_start;
copy(start_n, pos, old_start);
copy(first, last, pos - difference_type(n));
}
else {
ForwardIterator mid = first;
advance(mid, difference_type(n) - elems_before);
__uninitialized_copy_copy(start, pos, first, mid, new_start);
start = new_start;
copy(mid, last, old_start);
}
}
__STL_UNWIND(destroy_nodes_at_front(new_start));
}
else {
iterator new_finish = reserve_elements_at_back(n);
iterator old_finish = finish;
const difference_type elems_after = difference_type(length) - elems_before;
pos = finish - elems_after;
__STL_TRY {
if (elems_after > difference_type(n)) {
iterator finish_n = finish - difference_type(n);
uninitialized_copy(finish_n, finish, finish);
finish = new_finish;
copy_backward(pos, finish_n, old_finish);
copy(first, last, pos);
}
else {
ForwardIterator mid = first;
advance(mid, elems_after);
__uninitialized_copy_copy(mid, last, pos, finish, finish);
finish = new_finish;
copy(first, mid, pos);
}
}
__STL_UNWIND(destroy_nodes_at_back(new_finish));
}
} #else /* __STL_MEMBER_TEMPLATES */ template <class T, class Alloc, size_t BufSize>
void deque<T, Alloc, BufSize>::insert_aux(iterator pos,
const value_type* first,
const value_type* last,
size_type n)
{
const difference_type elems_before = pos - start;
size_type length = size();
if (elems_before < length / 2) {
iterator new_start = reserve_elements_at_front(n);
iterator old_start = start;
pos = start + elems_before;
__STL_TRY {
if (elems_before >= difference_type(n)) {
iterator start_n = start + difference_type(n);
uninitialized_copy(start, start_n, new_start);
start = new_start;
copy(start_n, pos, old_start);
copy(first, last, pos - difference_type(n));
}
else {
const value_type* mid = first + (difference_type(n) - elems_before);
__uninitialized_copy_copy(start, pos, first, mid, new_start);
start = new_start;
copy(mid, last, old_start);
}
}
__STL_UNWIND(destroy_nodes_at_front(new_start));
}
else {
iterator new_finish = reserve_elements_at_back(n);
iterator old_finish = finish;
const difference_type elems_after = difference_type(length) - elems_before;
pos = finish - elems_after;
__STL_TRY {
if (elems_after > difference_type(n)) {
iterator finish_n = finish - difference_type(n);
uninitialized_copy(finish_n, finish, finish);
finish = new_finish;
copy_backward(pos, finish_n, old_finish);
copy(first, last, pos);
}
else {
const value_type* mid = first + elems_after;
__uninitialized_copy_copy(mid, last, pos, finish, finish);
finish = new_finish;
copy(first, mid, pos);
}
}
__STL_UNWIND(destroy_nodes_at_back(new_finish));
}
} template <class T, class Alloc, size_t BufSize>
void deque<T, Alloc, BufSize>::insert_aux(iterator pos,
const_iterator first,
const_iterator last,
size_type n)
{
const difference_type elems_before = pos - start;
size_type length = size();
if (elems_before < length / 2) {
iterator new_start = reserve_elements_at_front(n);
iterator old_start = start;
pos = start + elems_before;
__STL_TRY {
if (elems_before >= n) {
iterator start_n = start + n;
uninitialized_copy(start, start_n, new_start);
start = new_start;
copy(start_n, pos, old_start);
copy(first, last, pos - difference_type(n));
}
else {
const_iterator mid = first + (n - elems_before);
__uninitialized_copy_copy(start, pos, first, mid, new_start);
start = new_start;
copy(mid, last, old_start);
}
}
__STL_UNWIND(destroy_nodes_at_front(new_start));
}
else {
iterator new_finish = reserve_elements_at_back(n);
iterator old_finish = finish;
const difference_type elems_after = length - elems_before;
pos = finish - elems_after;
__STL_TRY {
if (elems_after > n) {
iterator finish_n = finish - difference_type(n);
uninitialized_copy(finish_n, finish, finish);
finish = new_finish;
copy_backward(pos, finish_n, old_finish);
copy(first, last, pos);
}
else {
const_iterator mid = first + elems_after;
__uninitialized_copy_copy(mid, last, pos, finish, finish);
finish = new_finish;
copy(first, mid, pos);
}
}
__STL_UNWIND(destroy_nodes_at_back(new_finish));
}
} #endif /* __STL_MEMBER_TEMPLATES */ template <class T, class Alloc, size_t BufSize>
void deque<T, Alloc, BufSize>::new_elements_at_front(size_type new_elements) {
size_type new_nodes = (new_elements + buffer_size() - 1) / buffer_size();
reserve_map_at_front(new_nodes);
size_type i;
__STL_TRY {
for (i = 1; i <= new_nodes; ++i)
*(start.node - i) = allocate_node();
}
# ifdef __STL_USE_EXCEPTIONS
catch(...) {
for (size_type j = 1; j < i; ++j)
deallocate_node(*(start.node - j));
throw;
}
# endif /* __STL_USE_EXCEPTIONS */
} template <class T, class Alloc, size_t BufSize>
void deque<T, Alloc, BufSize>::new_elements_at_back(size_type new_elements) {
size_type new_nodes = (new_elements + buffer_size() - 1) / buffer_size();
reserve_map_at_back(new_nodes);
size_type i;
__STL_TRY {
for (i = 1; i <= new_nodes; ++i)
*(finish.node + i) = allocate_node();
}
# ifdef __STL_USE_EXCEPTIONS
catch(...) {
for (size_type j = 1; j < i; ++j)
deallocate_node(*(finish.node + j));
throw;
}
# endif /* __STL_USE_EXCEPTIONS */
} template <class T, class Alloc, size_t BufSize>
void deque<T, Alloc, BufSize>::destroy_nodes_at_front(iterator before_start) {
for (map_pointer n = before_start.node; n < start.node; ++n)
deallocate_node(*n);
} template <class T, class Alloc, size_t BufSize>
void deque<T, Alloc, BufSize>::destroy_nodes_at_back(iterator after_finish) {
for (map_pointer n = after_finish.node; n > finish.node; --n)
deallocate_node(*n);
} //重换一个 map (配置更大的,拷贝原来的,释放原来的)
template <class T, class Alloc, size_t BufSize>
void deque<T, Alloc, BufSize>::reallocate_map(size_type nodes_to_add,
bool add_at_front) {
size_type old_num_nodes = finish.node - start.node + 1;//旧节点数
size_type new_num_nodes = old_num_nodes + nodes_to_add;//新节点数 map_pointer new_nstart;
//当前 map 的大小大于新节点数的两倍的情况
//即当前 map 足够大,则调整节点区间让它落在 map 的中间
if (map_size > 2 * new_num_nodes) {
new_nstart = map + (map_size - new_num_nodes) / 2
+ (add_at_front ? nodes_to_add : 0);
if (new_nstart < start.node)
copy(start.node, finish.node + 1, new_nstart);
else
copy_backward(start.node, finish.node + 1, new_nstart + old_num_nodes);
}
//否则,配置一块新的空间
else {
size_type new_map_size = map_size + max(map_size, nodes_to_add) + 2; //配置一块新的空间
map_pointer new_map = map_allocator::allocate(new_map_size);
new_nstart = new_map + (new_map_size - new_num_nodes) / 2
+ (add_at_front ? nodes_to_add : 0);
//拷贝原 map
copy(start.node, finish.node + 1, new_nstart);
//释放原 map
map_allocator::deallocate(map, map_size);
//设定新 map 的起始地址和大小
map = new_map;
map_size = new_map_size;
}
//又一次设定迭代器 start 和 finish
start.set_node(new_nstart);
finish.set_node(new_nstart + old_num_nodes - 1);
} // Nonmember functions. #ifndef __STL_NON_TYPE_TMPL_PARAM_BUG template <class T, class Alloc, size_t BufSiz>
bool operator==(const deque<T, Alloc, BufSiz>& x,
const deque<T, Alloc, BufSiz>& y) {
return x.size() == y.size() && equal(x.begin(), x.end(), y.begin());
} template <class T, class Alloc, size_t BufSiz>
bool operator<(const deque<T, Alloc, BufSiz>& x,
const deque<T, Alloc, BufSiz>& y) {
return lexicographical_compare(x.begin(), x.end(), y.begin(), y.end());
} #endif /* __STL_NON_TYPE_TMPL_PARAM_BUG */ #if defined(__STL_FUNCTION_TMPL_PARTIAL_ORDER) && \
!defined(__STL_NON_TYPE_TMPL_PARAM_BUG) template <class T, class Alloc, size_t BufSiz>
inline void swap(deque<T, Alloc, BufSiz>& x, deque<T, Alloc, BufSiz>& y) {
x.swap(y);
} #endif #if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32)
#pragma reset woff 1174
#endif __STL_END_NAMESPACE #endif /* __SGI_STL_INTERNAL_DEQUE_H */ // Local Variables:
// mode:C++
// End:
STL源代码剖析 容器 stl_deque.h的更多相关文章
- 《STL源代码剖析》---stl_deque.h阅读笔记(2)
看完,<STL源代码剖析>---stl_deque.h阅读笔记(1)后.再看代码: G++ 2.91.57,cygnus\cygwin-b20\include\g++\stl_deque. ...
- STL源代码剖析 容器 stl_hashtable.h
本文为senlie原创.转载请保留此地址:http://blog.csdn.net/zhengsenlie hashtable ------------------------------------ ...
- STL源代码剖析 容器 stl_map.h
本文为senlie原创,转载请保留此地址:http://blog.csdn.net/zhengsenlie map ------------------------------------------ ...
- STL源代码剖析 容器 stl_list.h
本文为senlie原创.转载请保留此地址:http://blog.csdn.net/zhengsenlie list ----------------------------------------- ...
- STL源代码剖析 容器 stl_stack.h
本文为senlie原创,转载请保留此地址:http://blog.csdn.net/zhengsenlie stack ---------------------------------------- ...
- STL源代码剖析 容器 stl_vector.h
本文为senlie原创.转载请保留此地址:http://blog.csdn.net/zhengsenlie vector --------------------------------------- ...
- 《STL源代码剖析》---stl_alloc.h阅读笔记
这一节是讲空间的配置与释放,但不涉及对象的构造和析构,仅仅是解说对象构造前空前的申请以及对象析构后空间怎么释放. SGI版本号的STL对空间的的申请和释放做了例如以下考虑: 1.向堆申请空间 2.考虑 ...
- 《STL源代码剖析》---stl_set.h阅读笔记
SET是STL中的标准容器,SET里面的元素会依据键值自己主动排序,它不像map那样拥有实值value和键值key的相应,set仅仅有实值.SET的底层实现时RB-tree,当插入到RB-tree中后 ...
- 《STL源代码剖析》---stl_hash_set.h阅读笔记
STL仅仅规定接口和复杂度,对于详细实现不作要求.set大多以红黑树实现,但STL在标准规格之外提供了一个所谓的hash_set,以hash table实现.hash_set的接口,hash_tabl ...
随机推荐
- BZOJ 4369: [IOI2015]teams分组
把一个人看成二维平面上的一个点,把一个K[i]看成左上角为(0,+max),右下角为(K[i],K[i])的一个矩阵,那么可以很好地描述人对于询问是否合法(我也不知道他怎么想到这东西的) 然后把一组询 ...
- net clr via c sharp chap1-- note
Tag-> 托管代码 Tag-> .NET Framework 系统环境检测 Tag-> 设置平台 Tag-> 查询64或32位机 Tag-> IL编译成机器指令 Tag ...
- Python 爬取图书图片和地址
#-*- coding:utf-8 -*- import xlwt import urllib import re def getHtml(url): page = urllib.urlopen(ur ...
- PostgreSQL 全文索引
-- 首先要创建自定义的词典,在不使用停用词文件的情况下创建自定义词典,例如: CREATE TEXT SEARCH DICTIONARY english_stem_nostop ( Template ...
- Python socket粘包问题(最终解决办法)
套接字: 就是将传输层以下的协议封装成子接口 对于应用程序来说只需调用套接字的接口,写出的程序自然是遵循tcp或udp协议的 实现第一个功能个:实现:通过客户端向服务端发送命令,调取windows下面 ...
- hdu3667
Transportation Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)To ...
- git基本常用命令总结
官网:https://git-scm.com/book/zh/v1/Git-%E5%9F%BA%E7%A1%80-%E5%8F%96%E5%BE%97%E9%A1%B9%E7%9B%AE%E7%9A% ...
- NOJ——1649Find Sum(二分查找)
[1649] Find Sum 时间限制: 1000 ms 内存限制: 65535 K 问题描述 This problem is really boring. You are given a numb ...
- 说说IO(一)- IO的分层
IO性能对于一个系统的影响是至关重要的.一个系统经过多项优化以后,瓶颈往往落在数据库:而数据库经过多种优化以后,瓶颈最终会落到IO.而IO性能的发展,明显落后于CPU的发展.Memchached也好, ...
- 【python接口自动化】logger
#! /usr/bin/env python # coding=GBK import logging, os class Logger: def __init__(self, path, clevel ...