stl_deque.h
// Filename: stl_deque.h // Comment By: 凝霜
// E-mail: mdl2009@vip.qq.com
// Blog: http://blog.csdn.net/mdl13412 // 如果vector能满足你的需求, 那么就使用vector
// 如果不得不使用deque, 那么在进行一算法(尤其是sort)操作时
// 应该先把deque中的元素复制到vector中
// 执行完算法再复制回去
// 这样的效率往往要高于直接使用算法的效率 /*
*
* Copyright (c) 1994
* Hewlett-Packard Company
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies and
* that both that copyright notice and this permission notice appear
* in supporting documentation. Hewlett-Packard Company makes no
* representations about the suitability of this software for any
* purpose. It is provided "as is" without express or implied warranty.
*
*
* Copyright (c) 1997
* Silicon Graphics Computer Systems, Inc.
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies and
* that both that copyright notice and this permission notice appear
* in supporting documentation. Silicon Graphics makes no
* representations about the suitability of this software for any
* purpose. It is provided "as is" without express or implied warranty.
*/ /* NOTE: This is an internal header file, included by other STL headers.
* You should not attempt to use it directly.
*/ #ifndef __SGI_STL_INTERNAL_DEQUE_H
#define __SGI_STL_INTERNAL_DEQUE_H // 特性:
// 对于任何的非奇异(nonsingular)的迭代器i
// i.node是map array中的某元素的地址. i.node的内容是一个指向某个结点的头的指针
// i.first == *(i.node)
// i.last == i.first + node_size
// i.cur是一个指向[i.first, i.last)之间的指针
// 注意: 这意味着i.cur永远是一个可以解引用的指针,
// 即使其是一个指向结尾后元素的迭代器
//
// 起点和终点总是非奇异(nonsingular)的迭代器.
// 注意: 这意味着空deque一定有一个node, 而一个具有N个元素的deque
// (N是Buffer Size)一定有有两个nodes
//
// 对于除了start.node和finish.node之外的每一个node, 每一个node中的元素
// 都是一个初始化过的对象. 如果start.node == finish.node,
// 那么[start.cur, finish.cur)都是未初始化的空间.
// 否则, [start.cur, start.last)和[finish.first, finish.cur)都是初始化的对象,
// 而[start.first, start.cur)和[finish.cur, finish.last)是未初始化的空间
//
// [map, map + map_size)是一个合法的非空区间
// [start.node, finish.node]是内含在[map, map + map_size)区间的合法区间
// 一个在[map, map + map_size)区间内的指针指向一个分配过的node,
// 当且仅当此指针在[start.node, finish.node]区间内 // 在前一个版本的deque中, node_size被设定为定植.
// 然而在这个版本中, 用户可以自定义node_size的大小.
// deque有三个模板参数, 第三个参数为size_t类型, 代表每个结点内的元素数目.
// 如果第三个参数被设定为0(默认值), deque使用默认结点大小
//
// 使用不同结点大小的唯一理由是, 你的程序需要不同的效率, 并愿意为此付出代价,
// 例如, 如果你的程序中有许多deque, 但是每个deque都只包含很少的元素,
// 那么你可以使用较小的node_size来进行管理, 但是会对访问操作带来效率损失
//
// 不幸的是, 一些编译器不能正确处理non-type template parameters;
// 如果这样, 在<stl_config.h>会定义__STL_NON_TYPE_TMPL_PARAM_BUG
// 如果你的编译器不幸在列, 你只能使用默认的大小, 而不能更改 __STL_BEGIN_NAMESPACE #if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32)
#pragma set woff 1174
#endif // 这个函数是为了防止不同编译器在处理常量表达式时的Bug
// 如果n != 0, 那么就返回n, 表示buffer size为使用者自定义
// 如果n ==0, 就返回默认值表示buffer size,默认值计算方法如下
// 如果sz(元素类型大小sizeof(type))小于512, 返回512 / sz
// 否则返回1
inline size_t __deque_buf_size(size_t n, size_t sz)
{
return n != ? n : (sz < ? size_t( / sz) : size_t());
} // 注意这里未继承自std::iterator
#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(, sizeof(T)); }
#endif typedef random_access_iterator_tag iterator_category; // STL标准强制要求
typedef T value_type; // STL标准强制要求
typedef Ptr pointer; // STL标准强制要求
typedef Ref reference; // STL标准强制要求
typedef size_t size_type;
typedef ptrdiff_t difference_type; // STL标准强制要求
typedef T** map_pointer; typedef __deque_iterator self; // 保存容器中的结点
T* cur; // 指向当前缓冲区中的元素
T* first; // 当前缓冲区的起点
T* last; // 当前缓冲区的终点 ////////////////////////////////////////////////////////////////////////////////
// 这个是deque内存管理的关键, 其模型如下
////////////////////////////////////////////////////////////////////////////////
//
// ---------------------------------------------
// map-->| | | | | | | ..... | | | |<------------------
// --------------------------------------------- |
// | |
// | |
// | node |
// | 缓冲区buffer, 这里实际存储元素 |
// | --------------------------------------------- |
// --->| | | | | | | ..... | | | X | |
// --------------------------------------------- |
// ↑ ↑ ↑ |
// ------ | | |
// | | | |
// | ----------- --------------------------- |
// ----|----- | |
// | | | |
// | | | |
// | | | |
// --------------------------- |
// | cur | first | end | map |------------------------------
// ---------------------------
// 迭代器, 其内部维护着一个缓冲区状态
////////////////////////////////////////////////////////////////////////////////
map_pointer node; __deque_iterator(T* x, map_pointer y)
: cur(x), first(*y), last(*y + buffer_size()), node(y) {}
__deque_iterator() : cur(), first(), last(), node() {}
__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
// 如果编译器支持'->'则重载, 详细见我在<stl_list.h>中的剖析
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 - ) +
(cur - first) + (x.last - x.cur);
} ////////////////////////////////////////////////////////////////////////////////
// 下面重载的这些是运算符是让deque从外界看上去维护的是一段连续空间的关键!!!
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// 前缀自增
////////////////////////////////////////////////////////////////////////////////
// 如果当前迭代器指向元素是当前缓冲区的最后一个元素,
// 则将迭代器状态调整为下一个缓冲区的第一个元素
////////////////////////////////////////////////////////////////////////////////
// 不是当前缓冲区最后一个元素
//
// 执行前缀自增前的状态
// first cur end
// ↓ ↓ ↓
// ---------------------------------------------
// | | | | | | | ..... | | | X | <----- 当前缓冲区
// ---------------------------------------------
//
// 执行完成后的状态
// first cur end
// ↓ ↓ ↓
// ---------------------------------------------
// | | | | | | | ..... | | | X | <----- 当前缓冲区
// ---------------------------------------------
//
////////////////////////////////////////////////////////////////////////////////
// 当前元素为当前缓冲区的最后一个元素
//
// 执行前缀自增前的状态
// first cur end
// ↓ ↓ ↓
// ---------------------------------------------
// | | | | | | | ..... | | | X | <----- 当前缓冲区
// ---------------------------------------------
//
// 执行完成后的状态
// first end
// ↓ ↓
// ---------------------------------------------
// | | | | | | | ..... | | | X | <----- 下一缓冲区
// ---------------------------------------------
// ↑
// cur
//
////////////////////////////////////////////////////////////////////////////////
self& operator++()
{
++cur;
if (cur == last) {
set_node(node + );
cur = first;
}
return *this;
} // 后缀自增
// 返回当前迭代器的一个副本, 并调用前缀自增运算符实现迭代器自身的自增
self operator++(int) {
self tmp = *this;
++*this;
return tmp;
} // 前缀自减, 处理方式类似于前缀自增
// 如果当前迭代器指向元素是当前缓冲区的第一个元素
// 则将迭代器状态调整为前一个缓冲区的最后一个元素
self& operator--()
{
if (cur == first) {
set_node(node - );
cur = last;
}
--cur;
return *this;
} self operator--(int)
{
self tmp = *this;
--*this;
return tmp;
} ////////////////////////////////////////////////////////////////////////////////
// 将迭代器向前移动n个元素, n可以为负
////////////////////////////////////////////////////////////////////////////////
// operator+=(difference_type n)
// ↓
// offset = n + (cur - first)
// |
// |---------- offset > 0 ? &&
// | 移动后是否超出当前缓冲区?
// ----------------------------
// No | | Yes
// | |
// ↓ |---------- offset > 0?
// cur += n; |
// ----------------------------
// Yes | | No
// | |
// ↓ |
// 计算要向后移动多少个缓冲区 |
// node_offset = |
// offset / difference_type |
// (buffer_size()); ↓
// | 计算要向前移动多少个缓冲区
// | node_offset = -difference_type
// | ((-offset - 1) / buffer_size()) - 1;
// | |
// ----------------------------
// |
// |
// ↓
// 调整缓冲区
// set_node(node + node_offset);
// 计算并调整cur指针
//////////////////////////////////////////////////////////////////////////////// self& operator+=(difference_type n)
{
difference_type offset = n + (cur - first);
if (offset >= && offset < difference_type(buffer_size()))
cur += n;
else {
difference_type node_offset =
offset > ? offset / difference_type(buffer_size())
: -difference_type((-offset - ) / buffer_size()) - ;
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; // 这里调用了operator +=()可以自动调整指针状态
return tmp += n;
} // :-), 将n变为-n就可以使用operator +=()了,
// 初等数学是神奇的, 还记得我们刚学编程时求绝对值是怎么写的吗? :P
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);
} 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 ;
} template <class T, class Ref, class Ptr, size_t BufSiz>
inline ptrdiff_t* distance_type(const __deque_iterator<T, Ref, Ptr, BufSiz>&) {
return ;
} #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 ; } template <class T, class Ref, class Ptr>
inline ptrdiff_t* distance_type(const __deque_iterator<T, Ref, Ptr>&) {
return ;
} #endif /* __STL_NON_TYPE_TMPL_PARAM_BUG */ // 其实剖析到这里就没有什么难的了, deque的运算符才是核心
#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.
template <class T, class Alloc = alloc, size_t BufSiz = >
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 typedef pointer* map_pointer; // 这个提供STL标准的allocator接口, 见<stl_alloc.h>
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 ; } protected: // Data members
iterator start; // 起始缓冲区
iterator finish; // 最后一个缓冲区 // 指向map, map是一个连续的空间, 其每个元素都是一个指向缓冲区的指针
// 其模型见前面的__deque_iterator
map_pointer 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);
} // 提供随机访问能力, 其调用的是迭代器重载的operator []
// 其实际地址需要进行一些列的计算, 效率有损失
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() {
iterator tmp = finish;
--tmp;
return *tmp;
}
const_reference front() const { return *start; }
const_reference back() const {
const_iterator tmp = finish;
--tmp;
return *tmp;
} // 当前容器拥有的元素个数, 调用迭代器重载的operator -
size_type size() const { return finish - start;; }
size_type max_size() const { return size_type(-); } // deque为空的时, 只有一个缓冲区
bool empty() const { return finish == start; } public: // Constructor, destructor.
deque()
: start(), finish(), map(), map_size()
{
create_map_and_nodes();
} // 注: commit or rollback
deque(const deque& x)
: start(), finish(), map(), map_size()
{
create_map_and_nodes(x.size());
__STL_TRY {
uninitialized_copy(x.begin(), x.end(), start); // <stl_uninitialized.h>
}
__STL_UNWIND(destroy_map_and_nodes());
} deque(size_type n, const value_type& value)
: start(), finish(), map(), map_size()
{
fill_initialize(n, value);
} deque(int n, const value_type& value)
: start(), finish(), map(), map_size()
{
fill_initialize(n, value);
} deque(long n, const value_type& value)
: start(), finish(), map(), map_size()
{
fill_initialize(n, value);
} explicit deque(size_type n)
: start(), finish(), map(), map_size()
{
fill_initialize(n, value_type());
} #ifdef __STL_MEMBER_TEMPLATES template <class InputIterator>
deque(InputIterator first, InputIterator last)
: start(), finish(), map(), map_size()
{
range_initialize(first, last, iterator_category(first));
} #else /* __STL_MEMBER_TEMPLATES */ deque(const value_type* first, const value_type* last)
: start(), finish(), map(), map_size()
{
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(), map_size()
{
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); // <stl_construct.h>
destroy_map_and_nodes();
} deque& operator= (const deque& x)
{
// 其实我觉得把这个操作放在if内效率更高
const size_type len = size();
if (&x != this) {
// 当前容器比x容器拥有元素多, 析构多余元素
if (len >= x.size())
erase(copy(x.begin(), x.end(), start), finish);
// 将x所有超出部分的元素使用insert()追加进去
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)
{
// STL使用前闭后开的区间, 所以如果还有剩余容量,
// 则直接在finish.cur上构造对象即可, 然后更新迭代器
if (finish.cur != finish.last - ) {
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 - , 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 - )
{
destroy(start.cur);
++start.cur;
}
else
pop_front_aux();
} public: // Insert ////////////////////////////////////////////////////////////////////////////////
// 在指定位置前插入元素
////////////////////////////////////////////////////////////////////////////////
// insert(iterator position, const value_type& x)
// |
// |---------------- 判断插入位置
// |
// -----------------------------------------------
// deque.begin() | deque.emd() | |
// | | |
// ↓ ↓ |
// push_front(x); push_back(x); |
// ↓
// insert_aux(position, x);
// 具体剖析见后面实现
//////////////////////////////////////////////////////////////////////////////// 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;
}
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 */ // 如果new_size < size(), 那么就析构掉多余的元素,
// 否则以x为蓝本进行剩余元素的填充
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 iterator erase(iterator pos)
{
iterator next = pos;
++next; // 计算待擦除点前的元素个数
difference_type index = pos - start; // 判断待擦除结点前后元素的个数, 哪部分少就移动哪部分
if (index < (size() >> ))
{
// 前面部分的元素少
copy_backward(start, pos, next); // <stl_algobase.h>
pop_front();
}
// 后面部分的元素少
else {
copy(next, finish, pos); // <stl_algobase.h>
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 */ // 在起始缓冲区预留大小为n的空间
// 如果缓冲区不足则重新分配
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) - ;
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 = )
{
if (nodes_to_add + > map_size - (finish.node - map))
reallocate_map(nodes_to_add, false);
} void reserve_map_at_front (size_type nodes_to_add = )
{
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, >& x) const {
return size() == x.size() && equal(begin(), end(), x.begin());
}
bool operator!=(const deque<T, Alloc, >& x) const {
return size() != x.size() || !equal(begin(), end(), x.begin());
}
bool operator<(const deque<T, Alloc, >& x) const {
return lexicographical_compare(begin(), end(), x.begin(), x.end());
}
#endif /* __STL_NON_TYPE_TMPL_PARAM_BUG */
}; ////////////////////////////////////////////////////////////////////////////////
// 不进行内联的成员函数
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// 在指定位置前插入n个值为x的元素
////////////////////////////////////////////////////////////////////////////////
// insert(iterator pos, size_type n, const value_type& x)
// |
// |---------------- 判断插入位置
// |
// ---------------------------------------------------------
// deque.begin() | deque.end() | |
// | | |
// ↓ | |
// reserve_elements_at_front(n); | |
// uninitialized_fill(new_start, start, x); | |
// ↓ |
// reserve_elements_at_back(n); |
// uninitialized_fill(finish, new_finish, x); |
// ↓
// insert_aux(pos, n, x);
// 剖析见后面实现
//////////////////////////////////////////////////////////////////////////////// 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 */ ////////////////////////////////////////////////////////////////////////////////
// 擦除[first, last)区间的元素
////////////////////////////////////////////////////////////////////////////////
// erase(iterator first, iterator last)
// |
// |---------------- 是否要删除整个区间?
// |
// ------------------------------------------
// Yes | | No
// | |
// ↓ | --- 判断哪侧元素少
// clear(); ↓
// -----------------------------------------------------------------
// 左侧少 | 右侧少 |
// | |
// ↓ ↓
// copy_backward(start, first, last); copy(last, finish, first);
// new_start = start + n; new_finish = finish - n;
// 析构多余的元素 析构多余的元素
// destroy(start, new_start); destroy(new_finish, finish);
// 释放多余内存空间 释放多余内存空间
// for (...) for (...)
// ... ...
// 更新map状态 更新map状态
////////////////////////////////////////////////////////////////////////////////
template <class T, class Alloc, size_t BufSize>
deque<T, Alloc, BufSize>::iterator
deque<T, Alloc, BufSize>::erase(iterator first, iterator last)
{
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) / ) {
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 + ; cur <= finish.node; ++cur)
data_allocator::deallocate(*cur, buffer_size());
finish = new_finish;
}
return start + elems_before;
}
} template <class T, class Alloc, size_t BufSize>
void deque<T, Alloc, BufSize>::clear()
{
// 首先析构除起点和终点的所有元素, 并释放相应空间
for (map_pointer node = start.node + ; node < finish.node; ++node) {
destroy(*node, *node + buffer_size());
data_allocator::deallocate(*node, buffer_size());
} // 如果deque本身不为空, 析构所有对象, 并释放掉结尾的内存
if (start.node != finish.node) {
destroy(start.cur, start.last);
destroy(finish.first, finish.cur);
data_allocator::deallocate(finish.first, buffer_size());
}
// 析构所有元素, 但是不释放空间, 因为deque要满足这个前置条件
// 具体的细节见本文件开头'特性'
else
destroy(start.cur, finish.cur); finish = start;
} // 创建内部使用的map
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() + ; // map要维护的结点, 这里最小的值为8, 见initial_map_size()
map_size = max(initial_map_size(), num_nodes + );
map = map_allocator::allocate(map_size); // 将[nstart, nfinish)区间设置在map的中间,
// 这样就能保证前后增长而尽可能减少map的重新分配次数
map_pointer nstart = map + (map_size - num_nodes) / ;
map_pointer nfinish = nstart + num_nodes - ; // 分配结点空间
map_pointer cur;
__STL_TRY {
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 */ // 维护指针状态
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);
} // 分配n个结点, 并以value为蓝本初始化
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);
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();
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 = ;
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 + ) = allocate_node();
__STL_TRY {
construct(finish.cur, t_copy);
finish.set_node(finish.node + );
finish.cur = finish.first;
}
__STL_UNWIND(deallocate_node(*(finish.node + )));
} // Called only if start.cur == start.first.
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 - ) = allocate_node();
__STL_TRY {
start.set_node(start.node - );
start.cur = start.last - ;
construct(start.cur, t_copy);
}
# ifdef __STL_USE_EXCEPTIONS
catch(...) {
start.set_node(start.node + );
start.cur = start.first;
deallocate_node(*(start.node - ));
throw;
}
# endif /* __STL_USE_EXCEPTIONS */
} // Called only if 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 - );
finish.cur = finish.last - ;
destroy(finish.cur);
} // Called only if start.cur == start.last - 1. Note that if the deque
// has at least one element (a necessary precondition for this member
// function), and if start.cur == start.last, then the deque must have
// at least two nodes.
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 + );
start.cur = start.first;
} #ifdef __STL_MEMBER_TEMPLATES // 将[first, last)区间元素插入到pos前 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)
{
// 由于是Input Iterator, 则使用通用的inserter完成插入操作
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 = ;
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 */ ////////////////////////////////////////////////////////////////////////////////
// 在指定位置前插入元素
////////////////////////////////////////////////////////////////////////////////
// insert_aux(iterator pos, const value_type& x)
// |
// |----------- 判断pos前端元素少还是后端元素少
// |
// -----------------------------------------------
// 前端少 | 后端少 |
// | |
// ↓ |
// 进行相关操作 进行相关操作
////////////////////////////////////////////////////////////////////////////////
// 下面以pos前面元素少的情形进行说明, 为了简化, 假设操作不会超过一个缓冲区区间
//
// 插入前状态
// start pos end
// ↓ ↓ ↓
// ---------------------------------------------------------------------
// | | | | | | | | | | | | | | | | | X |
// ---------------------------------------------------------------------
//
// 需要进行操作的区间
// 需要拷贝的区间
// -------------
// start | | end
// ↓ ↓ ↓ ↓
// ---------------------------------------------------------------------
// | | | | | | | | | | | | | | | | | X |
// ---------------------------------------------------------------------
// ↑ ↑ ↑ ↑
// front1 | | |
// | | |
// front2 | |
// | |
// pos |
// |
// pos1
// 拷贝操作完成后
//
// 这是[front2, pos1)
// ------------- --------- 这里是给待插入元素预留的空间
// start | | | end
// ↓ ↓ ↓ ↓ ↓
// ---------------------------------------------------------------------
// | | | | | | | | | | | | | | | | | X |
// ---------------------------------------------------------------------
// ↑
// 这里存储的是原来的front()
//
//////////////////////////////////////////////////////////////////////////////// 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() / ) {
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;
} ////////////////////////////////////////////////////////////////////////////////
// 在pos前插入n个值为x的元素
////////////////////////////////////////////////////////////////////////////////
// insert_aux(iterator pos, size_type n, const value_type& x)
// ↓
// elems_before = pos - start;
// length = size();
// |
// |---------- elems_before < length / 2 ?
// | 判断哪侧元素少, 就对哪侧进行操作
// ---------------------------------------
// Yes | | No
// | |
// ↓ ↓
// reserve_elements_at_front(n); reserve_elements_at_back(n);
// 根据具体情况进行元素的拷贝操作 根据具体情况进行元素的拷贝操作
//////////////////////////////////////////////////////////////////////////////// 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 / ) {
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 // 供给insert(iterator pos, ForwardIterator first, ForwardIterator last,)
// 处理通用情况
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 / ) {
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 / ) {
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 / ) {
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 */ // 在deque前端分配新结点
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() - ) / buffer_size();
reserve_map_at_front(new_nodes);
size_type i;
__STL_TRY {
for (i = ; i <= new_nodes; ++i)
*(start.node - i) = allocate_node();
}
# ifdef __STL_USE_EXCEPTIONS
catch(...) {
for (size_type j = ; j < i; ++j)
deallocate_node(*(start.node - j));
throw;
}
# endif /* __STL_USE_EXCEPTIONS */
} // 在deque末尾分配新结点
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() - ) / buffer_size();
reserve_map_at_back(new_nodes);
size_type i;
__STL_TRY {
for (i = ; i <= new_nodes; ++i)
*(finish.node + i) = allocate_node();
}
# ifdef __STL_USE_EXCEPTIONS
catch(...) {
for (size_type j = ; j < i; ++j)
deallocate_node(*(finish.node + j));
throw;
}
# endif /* __STL_USE_EXCEPTIONS */
} // 释放[before_start.node, start.node)的结点
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);
} // 释放(finish.node, after_finish.node]的结点
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, 不会对缓冲区进行操作, 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 + ;
size_type new_num_nodes = old_num_nodes + nodes_to_add; map_pointer new_nstart;
if (map_size > * new_num_nodes) {
new_nstart = map + (map_size - new_num_nodes) /
+ (add_at_front ? nodes_to_add : );
if (new_nstart < start.node)
copy(start.node, finish.node + , new_nstart);
else
copy_backward(start.node, finish.node + , new_nstart + old_num_nodes);
}
else {
size_type new_map_size = map_size + max(map_size, nodes_to_add) + ; map_pointer new_map = map_allocator::allocate(new_map_size);
new_nstart = new_map + (new_map_size - new_num_nodes) /
+ (add_at_front ? nodes_to_add : );
copy(start.node, finish.node + , new_nstart);
map_allocator::deallocate(map, map_size); map = new_map;
map_size = new_map_size;
} start.set_node(new_nstart);
finish.set_node(new_nstart + old_num_nodes - );
} // 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_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_deque.h

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

  3. C++ string::size_type 类型【转】

    int main() { string str("Hello World!\n"); cout << "The size of " << ...

  4. 关于size_t与size_type

    整理自关于size_t与size_type 问题起源于这样一段代码: #include <algorithm> #include <stdio.h> int main() { ...

  5. STL-Deque 源码剖析

    G++ ,cygnus\cygwin-b20\include\g++\stl_deque.h 完整列表 /* * * Copyright (c) 1994 * Hewlett-Packard Comp ...

  6. C语言 string::size_type类型

    string::size_type类型 从逻辑上来讲,size()成员函数似乎应该返回整型数值,或如2.2节“建议”中所述的无符号整数.但事实上,size操作返回的是string::size_type ...

  7. C++ STL源码剖析

    stl_config.h defalloc.h stl_alloc.h memory.cpp stl_construct.h stl_uninitialized.h stl_iterator.h ty ...

  8. C++ STL 源代码学习(之deque篇)

    stl_deque.h /** Class invariants: * For any nonsingular iterator i: * i.node is the address of an el ...

  9. std::map使用结构体自定义键值

    使用STL中的map时候,有时候需要使用结构题自定义键值,比如想统计点的坐标出现的次数 struct Node{ int x,y; }; ...... map<Node,int>mp; m ...

随机推荐

  1. 【python系列】python画报表(Chartkick、Flask)(附中文乱码解决方式)

    chartkick 能够画 javascript 报表, 并且比較美观.可是网上搜了下.非常难找到 python 版本号的,于是查了些资料,摸索了下. 对 Flask 也不非常熟悉,这里就仅仅抛砖引玉 ...

  2. 【BZOJ2081】[Poi2010]Beads hash+调和级数

    [BZOJ2081][Poi2010]Beads Description Zxl有一次决定制造一条项链,她以非常便宜的价格买了一长条鲜艳的珊瑚珠子,她现在也有一个机器,能把这条珠子切成很多块(子串), ...

  3. elasticsearch从入门到出门-05-集群之踩坑

    自己搭的集群, 设备: win10 + ubuntu 16 的虚拟机一个: 下载的版本:elasticsearch-5.2.0 win10 解压下就好了,不说了. ubuntu 上,我想说多了都是泪! ...

  4. 在普通网页中如何调用html5+的plus对象

    <script> //用法: HTML5+的plus对象,必须由click事件触发后,才能在普通网页中使用.所以在没有click的情况下,调用本文件可以解决问题! //在代码中使用: pl ...

  5. 【python】-- web开发之CSS

    CSS CSS作用概述:(通俗的讲就是将HTML这个赤裸裸的“人”,穿上华丽的衣服) CSS 指层叠样式表 (Cascading Style Sheets) 样式定义如何显示 HTML 元素 样式通常 ...

  6. centos7 Authentication failure

    root@localhost ~]#su bash-4.2$ su Password: su: Authentication failure //这里切换的是系统用户,现在还不清楚为什么postgre ...

  7. 说说JSON和JSONP,也许你会豁然开朗,含jQuery用例(转载)

     前言: 说到AJAX就会不可避免的面临两个问题,第一个是AJAX以何种格式来交换数据?第二个是跨域的需求如何解决?这两个问题目前都有不同的解决方案,比如数据可以用自定义字符串或者用XML来描述,跨域 ...

  8. READ_TEXT

    [转自http://lz357502668.blog.163.com/blog/static/1649674320109119101907/]这里,定义ITAB内表来存储长文本,并放到内表ITAB_E ...

  9. C#聚合运算方法

    Aggregate 对集合值执行自定义聚合运算 Average 计算集合平均值 Count 对集合的元素惊醒计数,还可以仅对满足某一谓词函数的元素进行计数 LongCount 对大型集合中的元素进行计 ...

  10. 坑爹的shell 空格

    shell 空格很敏感,被线上代码坑了,占个位,回头好好整理一下