deque 容器的分段存储结构,提高了在序列两端添加或删除元素的效率,但也使该容器迭代器的底层实现变得更复杂。有读者可能会问,如果 map 数组满了怎么办?很简单,再申请一块更大的连续空间供 map 数组使用,将原有数据(很多指针)拷贝到新的 map 数组中,然后释放旧的空间。
template<class T,...> struct __deque_iterator{ ... T* cur; T* first; T* last; map_pointer node;//map_pointer 等价于 T** }可以看到,迭代器内部包含 4 个指针,它们各自的作用为:
//当迭代器处于当前连续空间边缘的位置时,如果继续遍历,就需要跳跃到其它的连续空间中,该函数可用来实现此功能 void set_node(map_pointer new_node){ node = new_node;//记录新的连续空间在 map 数组中的位置 first = *new_node; //更新 first 指针 //更新 last 指针,difference_type(buffer_size())表示每段连续空间的长度 last = first + difference_type(buffer_size()); } //重载 * 运算符 reference operator*() const{return *cur;} pointer operator->() const{return &(operator *());} //重载前置 ++ 运算符 self & operator++(){ ++cur; //处理 cur 处于连续空间边缘的特殊情况 if(cur == last){ //调用该函数,将迭代器跳跃到下一个连续空间中 set_node(node+1); //对 cur 重新赋值 cur = first; } return *this; } //重置前置 -- 运算符 self& operator--(){ //如果 cur 位于连续空间边缘,则先将迭代器跳跃到前一个连续空间中 if(cur == first){ set_node(node-1); cur == last; } --cur; return *this; }
//_Alloc为内存分配器 template<class _Ty, class _Alloc = allocator<_Ty>> class deque{ ... protected: iterator start; iterator finish; map_pointer map; ... }其中,start 迭代器记录着 map 数组中首个连续空间的信息,finish 迭代器记录着 map 数组中最后一个连续空间的信息。另外需要注意的是,和普通 deque 迭代器不同,start 迭代器中的 cur 指针指向的是连续空间中首个元素;而 finish 迭代器中的 cur 指针指向的是连续空间最后一个元素的下一个位置。
//begin() 成员函数 iterator begin() {return start;} //end() 成员函数 iterator end() { return finish;} //front() 成员函数 reference front(){return *start;} //back() 成员函数 reference back(){ iterator tmp = finish; --tmp; return *tmp; } //size() 成员函数 size_type size() const{return finish - start;}//deque迭代器重载了 - 运算符 //enpty() 成员函数 bool empty() const{return finish == start;}
Copyright © 广州京杭网络科技有限公司 2005-2024 版权所有 粤ICP备16019765号
广州京杭网络科技有限公司 版权所有