本文为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的更多相关文章

  1. 《STL源代码剖析》---stl_deque.h阅读笔记(2)

    看完,<STL源代码剖析>---stl_deque.h阅读笔记(1)后.再看代码: G++ 2.91.57,cygnus\cygwin-b20\include\g++\stl_deque. ...

  2. STL源代码剖析 容器 stl_hashtable.h

    本文为senlie原创.转载请保留此地址:http://blog.csdn.net/zhengsenlie hashtable ------------------------------------ ...

  3. STL源代码剖析 容器 stl_map.h

    本文为senlie原创,转载请保留此地址:http://blog.csdn.net/zhengsenlie map ------------------------------------------ ...

  4. STL源代码剖析 容器 stl_list.h

    本文为senlie原创.转载请保留此地址:http://blog.csdn.net/zhengsenlie list ----------------------------------------- ...

  5. STL源代码剖析 容器 stl_stack.h

    本文为senlie原创,转载请保留此地址:http://blog.csdn.net/zhengsenlie stack ---------------------------------------- ...

  6. STL源代码剖析 容器 stl_vector.h

    本文为senlie原创.转载请保留此地址:http://blog.csdn.net/zhengsenlie vector --------------------------------------- ...

  7. 《STL源代码剖析》---stl_alloc.h阅读笔记

    这一节是讲空间的配置与释放,但不涉及对象的构造和析构,仅仅是解说对象构造前空前的申请以及对象析构后空间怎么释放. SGI版本号的STL对空间的的申请和释放做了例如以下考虑: 1.向堆申请空间 2.考虑 ...

  8. 《STL源代码剖析》---stl_set.h阅读笔记

    SET是STL中的标准容器,SET里面的元素会依据键值自己主动排序,它不像map那样拥有实值value和键值key的相应,set仅仅有实值.SET的底层实现时RB-tree,当插入到RB-tree中后 ...

  9. 《STL源代码剖析》---stl_hash_set.h阅读笔记

    STL仅仅规定接口和复杂度,对于详细实现不作要求.set大多以红黑树实现,但STL在标准规格之外提供了一个所谓的hash_set,以hash table实现.hash_set的接口,hash_tabl ...

随机推荐

  1. 详解Python中的相对导入和绝对导入

    Python 相对导入与绝对导入,这两个概念是相对于包内导入而言的.包内导入即是包内的模块导入包内部的模块. Python import 的搜索路径 在当前目录下搜索该模块 在环境变量 PYTHONP ...

  2. python基础学习笔记——异常处理

    异常处理流程图 一,异常和错误 part1:程序中难免出现错误,而错误分成两种 1.语法错误(这种错误,根本过不了python解释器的语法检测,必须在程序执行前就改正) #语法错误示范一 if #语法 ...

  3. 03_HibernateSessionFactory源码分析

    文章导读: 讲解了一个线程为什么要使用同一个connection, 我们分析了HiberatenSessionFactory的实现机制, 然后根据Hibernate的写法重构了我们的代码. 最后测试可 ...

  4. LRESULT CALLBACK WndProc 窗口程序的 重点

    LRESULT CALLBACK WndProc Windows程序所作的一切,都是回应发送给窗口消息处理程序的消息.这是概念上的主要难点之一,在开始写作Windows程序之前,必须先搞清楚. 窗口消 ...

  5. Selenium WebDriver-通过ActionChains实现页面元素拖拽

    #encoding=utf-8 import unittest import time import chardet from selenium import webdriver class Visi ...

  6. Flowerpot(单调队列)

    描述 Farmer John has been having trouble making his plants grow, and needs your help to water them pro ...

  7. Tinkoff Internship Warmup Round 2018 and Codeforces Round #475 (Div. 2)

    A. Splits time limit per test 1 second memory limit per test 256 megabytes input standard input outp ...

  8. BZOJ-2829 信用卡凸包

    凸包题. 我们先把所有信用卡的四个定点的坐标求出来,然后计算凸包长度,最后加上一个圆的周长就行. #include <cstdlib> #include <cstdio> #i ...

  9. (转)解决fasterxml中string字符串转对象json格式错误问题(无引号 单引号问题)

    原文地址:解决fasterxml中string字符串转对象json格式错误问题 com.fasterxml.jackson.databind.ObjectMapper mapper = new com ...

  10. [转] Makefile 基础 (10) —— Makefile 后序

    该篇文章为转载,是对原作者系列文章的总汇加上标注. 支持原创,请移步陈浩大神博客:(最原始版本) http://blog.csdn.net/haoel/article/details/2886 我转自 ...