STL学习笔记:deque

这个deque看的我真是累。问题太多了,所以因此打算换一个看。而且后面的map和set也不全,后面看似乎是基于AVL而不是RBT实现的,所以换一个。作者还是很厉害的,毕竟让我自己写,目前水平肯定写不出来。但是吐槽还是要吐的
deque.h

#ifndef _DEQUE_H_
#define _DEQUE_H_

#include "Allocator.h"
#include "Iterator.h"
#include "ReverseIterator.h"
#include "Utility.h"

/*deque的实现较为复杂,因为是双向开口,所以涉及到内存分配,如何让他表现的像一个双向开口
deque通过一个地址数组的指针map_来实现。deque每次申请内存是申请一个大小为mapSize_的数组,这个数组里面放的是迭代器指针
这个deque的设计跟《STL源码剖析》小处有不同。二者deque的成员变量都一样,deque两端的两个迭代器,指向某个缓冲池的指针,整个缓冲区包含缓冲池的数目
但是iterate变量不同,STL中包括本缓冲池地址,本缓冲池的首尾地址,当前迭代器地址
而这个文件的iterate设计是三个,缓冲池大小,deque的地址,以及当前迭代器地址。想法是不错,但是mapindex的相关操作真的是令人费解。
既像是不变的=BUCKSIZE,但还有加减变化,但在getBuckTail那里又像是=0。又像是当前cur的索引
最后这个deque设计的着实有点差,在cpp文件中有更多说明
*/

namespace TinySTL{
    
    
	template<class T, class Alloc = allocator<T> >
	class deque;
	namespace Detail{
    
    
		//class of deque iterator
		template<class T>
		class dq_iter :public iterator<bidirectional_iterator_tag, T>{
    
    //继承迭代器的内嵌类型:双向迭代器
		private:
			template<class T, class Alloc>
			friend class ::TinySTL::deque;//互为友元

		private:
			//typedef TinySTL::deque<T>* cntrPtr;??为什么要加const
			typedef const ::TinySTL::deque<T>* cntrPtr;
			size_t mapIndex_;//==缓冲池大小
			T *cur_;//本迭代器地址
			cntrPtr container_;//容器deque的地址

		public:
			//三种初始化
			dq_iter() :mapIndex_(-1), cur_(0), container_(0){
    
    }
			dq_iter(size_t index, T *ptr, cntrPtr container)
				:mapIndex_(index), cur_(ptr), container_(container){
    
    }
			dq_iter(const dq_iter& it) 
				:mapIndex_(it.mapIndex_), cur_(it.cur_), container_(it.container_){
    
    }
			
			//重载运算符
			dq_iter& operator = (const dq_iter& it);
			reference operator *(){
    
     return *cur_; }//dq_iter是dque的友元类
			const reference operator *()const{
    
     return *cur_; }//pointer继承自iterator
			pointer operator ->(){
    
     return &(operator*()); }
			const pointer operator ->()const{
    
     return &(operator*()); }//只能由常量指针接收
			dq_iter& operator ++();
			dq_iter operator ++(int);
			dq_iter& operator --();
			dq_iter operator --(int);
			
			//下面几个应该为友元函数?
			bool operator ==(const dq_iter& it)const;
			bool operator !=(const dq_iter& it)const;
			void swap(dq_iter& it);//交换迭代器

		private:
			T *getBuckTail(size_t mapIndex)const;
			T *getBuckHead(size_t mapIndex)const;
			size_t getBuckSize()const;
		public:
            //全局友元函数重载运算符
			template<class T>//
			friend dq_iter<T> operator + (const dq_iter<T>& it, typename dq_iter<T>::difference_type n);
			template<class T>
			friend dq_iter<T> operator + (typename dq_iter<T>::difference_type n, const dq_iter<T>& it);
			template<class T>
			friend dq_iter<T> operator - (const dq_iter<T>& it, typename dq_iter<T>::difference_type n);
			template<class T>
			friend dq_iter<T> operator - (typename dq_iter<T>::difference_type n, const dq_iter<T>& it);
			template<class T>//求迭代器距离
			friend typename dq_iter<T>::difference_type operator - (const dq_iter<T>& it1, const dq_iter<T>& it2);
			template<class T>
			friend void swap(dq_iter<T>& lhs, dq_iter<T>& rhs);
		};
	}// end of Detail namespace

	//class of deque
	template<class T, class Alloc>
	class deque{
    
    
	private:
		template<class T>
		friend class ::TinySTL::Detail::dq_iter;

	public:
		typedef T 							value_type;
		typedef Detail::dq_iter<T> 			iterator;
		typedef Detail::dq_iter<const T> 	const_iterator;
		typedef T& 							reference;
		typedef const reference 			const_reference;
		typedef size_t 						size_type;
		typedef ptrdiff_t 					difference_type;
		typedef Alloc 						allocator_type;

	private:
		typedef Alloc dataAllocator;//跟上面的区别?
		enum class EBucksSize{
    
    BUCKSIZE = 64};

	private:
		iterator begin_, end_;//两个迭代器
		size_type mapSize_;//缓冲池数量
		T** map_;//迭代器数组指针

	public:
        //构造、复制、析构
		deque();//显式初始化
		explicit deque(size_type n, const value_type& val = value_type());
		template <class InputIterator>
		deque(InputIterator first, InputIterator last);
		deque(const deque& x);
		deque& operator= (const deque& x);
		deque& operator= (deque&& x);
		~deque();

        //迭代器设计
		iterator begin();
		iterator end();
		iterator begin()const;
		iterator end()const;
	public:

        //迭代器相关
		size_type size() const{
    
     return end() - begin(); }
		bool empty() const{
    
     return begin() == end(); }
		reference operator[] (size_type n);
		reference front();
		reference back();
		const_reference operator[] (size_type n) const;
		const_reference front() const;
		const_reference back() const;

        //接口函数
		void push_back(const value_type& val);
		void push_front(const value_type& val);
		void pop_back();
		void pop_front();
		void swap(deque& x);
		void clear();
	private:
        //内部实现函数
		T *getANewBuck();
		T** getANewMap(const size_t size);
		size_t getNewMapSize(const size_t size);
		size_t getBuckSize()const;
		void init();
		bool back_full()const;
		bool front_full()const;
		void deque_aux(size_t n, const value_type& val, std::true_type);
		template<class Iterator>
		void deque_aux(Iterator first, Iterator last, std::false_type);
		void reallocateAndCopy();
	public:
        //全局友元函数。==、!=、<<、>>都要如此定义
		template <class T, class Alloc>
		friend bool operator== (const deque<T, Alloc>& lhs, const deque<T, Alloc>& rhs);
		template <class T, class Alloc>
		friend bool operator!= (const deque<T, Alloc>& lhs, const deque<T, Alloc>& rhs);
		template <class T, class Alloc>
		friend void swap(deque<T, Alloc>& x, deque<T, Alloc>& y);
	};//end of deque
}

#include "Detail\Deque.cpp"
#endif

deque.cpp

#ifndef _DEQUE_IMPL_H_
#define _DEQUE_IMPL_H_

/*
这个deque,有很多细节设计的不好
*/

namespace TinySTL{
    
    
	namespace Detail{
    
    

        //重载迭代器运算符1
        //自增
		template<class T>
		dq_iter<T>& dq_iter<T>::operator ++(){
    
    
			if (cur_ != getBuckTail(mapIndex_))//
				++cur_;
			else if (mapIndex_ + 1 < container_->mapSize_){
    
    
				++mapIndex_;
				cur_ = getBuckHead(mapIndex_);
			}
			else{
    
    //+1后跳出了map
				mapIndex_ = container_->mapSize_;
				//cur_ = container_->map_[mapIndex_] + getBuckSize();//指向map_[mapSize_-1]的尾的下一个位置
				cur_ = container_->map_[mapIndex_];
			}
			return *this;
		}
        //后置++
		template<class T>
		dq_iter<T> dq_iter<T>::operator ++(int){
    
    
			auto res = *this;
			++(*this);
			return res;
		}
        //前置--
		template<class T>
		dq_iter<T>& dq_iter<T>::operator --(){
    
    
			if (cur_ != getBuckHead(mapIndex_))//当前不指向桶头
				--cur_;
			else if (mapIndex_ - 1 >= 0){
    
    //-1后还在map里面
				--mapIndex_;
				cur_ = getBuckTail(mapIndex_);
			}
			else{
    
    
				mapIndex_ = 0;
				cur_ = container_->map_[mapIndex_];//指向map_[0]的头
			}
			return *this;
		}
        //后置--
		template<class T>
		dq_iter<T> dq_iter<T>::operator --(int){
    
    
			auto res = *this;
			--(*this);
			return res;
		}

		template<class T>
		void swap(dq_iter<T>& lhs, dq_iter<T>& rhs){
    
    
			lhs.swap(rhs);
		}

        //重载运算符2
        //+运算
		template<class T>
		dq_iter<T> operator + (const dq_iter<T>& it, typename dq_iter<T>::difference_type n){
    
    //assume n >= 0
			dq_iter<T> res(it);
			auto m = res.getBuckTail(res.mapIndex_) - res.cur_;
			if (n <= m){
    
    //前进n步仍在同一个桶中
				res.cur_ += n;
			}
			else{
    
    
				n = n - m;
				res.mapIndex_ += (n / it.getBuckSize() + 1);
				auto p = res.getBuckHead(res.mapIndex_);
				auto x = n % it.getBuckSize() - 1;
				res.cur_ = p + x;
			}
			return res;
		}
		template<class T>
		dq_iter<T> operator + (typename dq_iter<T>::difference_type n, const dq_iter<T>& it){
    
    
			return (it + n);
		}
        //-运算
		template<class T>
		dq_iter<T> operator - (const dq_iter<T>& it, typename dq_iter<T>::difference_type n){
    
    //assume n >= 0
			dq_iter<T> res(it);
			auto m = res.cur_ - res.getBuckHead(res.mapIndex_);
			if (n <= m)//后退n步还在同一个桶中
				res.cur_ -= n;
			else{
    
    
				n = n - m;
				res.mapIndex_ -= (n / res.getBuckSize() + 1);
				res.cur_ = res.getBuckTail(res.mapIndex_) - (n % res.getBuckSize() - 1);
			}
			return res;
		}
		template<class T>
		dq_iter<T> operator - (typename dq_iter<T>::difference_type n, const dq_iter<T>& it){
    
    
			return (it - n);
		}

        //求距离
        template<class T>
		typename dq_iter<T>::difference_type operator - (const dq_iter<T>& it1, const dq_iter<T>& it2){
    
    
			if (it1.container_ == it2.container_ && it1.container_ ==0)//这个比较不奇怪吗?
				return 0;
			return typename dq_iter<T>::difference_type(it1.getBuckSize()) * (it1.mapIndex_ - it2.mapIndex_ - 1)
				+ (it1.cur_ - it1.getBuckHead(it1.mapIndex_)) + (it2.getBuckTail(it2.mapIndex_) - it2.cur_) + 1;
		}

        //复制
        template<class T>
		dq_iter<T>& dq_iter<T>::operator = (const dq_iter& it){
    
    
			if (this != &it){
    
    
				mapIndex_ = it.mapIndex_;
				cur_ = it.cur_;
				container_ = it.container_;
			}
			return *this;
		}


        //缓冲池相关操作
		template<class T>
		T *dq_iter<T>::getBuckTail(size_t mapIndex)const{
    
    
			return container_->map_[mapIndex] + (container_->getBuckSize() - 1);//container_->map_[mapIndex]-1);这样不好吗?
		}
		template<class T>
		T *dq_iter<T>::getBuckHead(size_t mapIndex)const{
    
    
			return container_->map_[mapIndex];
		}
		template<class T>
		size_t dq_iter<T>::getBuckSize()const{
    
    //缓冲池数组大小
			return container_->getBuckSize();
		}
	}//end of Detail namespace


    //迭代器相关函数
	template<class T, class Alloc>
	typename deque<T, Alloc>::reference deque<T, Alloc>::operator[] (size_type n){
    
    
		return *(begin() + n);
	}
	template<class T, class Alloc>
	typename deque<T, Alloc>::reference deque<T, Alloc>::front(){
    
    
		return *begin();
	}
	template<class T, class Alloc>
	typename deque<T, Alloc>::reference deque<T, Alloc>::back(){
    
    
		return *(end() - 1);
	}
	//由于const迭代器的设计失误故以下三个const函数会丧失const特性
	template<class T, class Alloc>
	typename deque<T, Alloc>::const_reference deque<T, Alloc>::operator[] (size_type n) const{
    
    
		return *(begin() + n);
	}
	template<class T, class Alloc>
	typename deque<T, Alloc>::const_reference deque<T, Alloc>::front() const{
    
    
		return *begin();
	}
	template<class T, class Alloc>
	typename deque<T, Alloc>::const_reference deque<T, Alloc>::back() const{
    
    
		return *(end() - 1);
	}
	template<class T, class Alloc>
	typename deque<T, Alloc>::iterator deque<T, Alloc>::begin(){
    
     return begin_; }
	template<class T, class Alloc>
	typename deque<T, Alloc>::iterator deque<T, Alloc>::end(){
    
     return end_; }
	//迭代器设计失误,会使下面两个函数丧失const特性,暂时没有效解决办法故只能先这样妥协
	template<class T, class Alloc>
	typename deque<T, Alloc>::iterator deque<T, Alloc>::begin()const{
    
     return begin_; }
	template<class T, class Alloc>
	typename deque<T, Alloc>::iterator deque<T, Alloc>::end()const{
    
     return end_; }
    //析构函数
	template<class T, class Alloc>
	deque<T, Alloc>::~deque(){
    
    
		for (int i = 0; i != mapSize_; ++i){
    
    
			for (auto p = map_[i] + 0; !p && p != map_[i] + getBuckSize(); ++p)
				dataAllocator::destroy(p);
			if (!map_[i])
				dataAllocator::deallocate(map_[i], getBuckSize());
		}
		delete[] map_;
	}

    //构造函数,这个deque构造函数就写的不好
    /*无参构造,没有,只给了两个默认参数,那么问题来了,他的初始化在什么地方呢?只能在插入第一个元素的时候,那么问题来了
    初始化首先要经过empty(),但是没有给begin_和end_赋初值,所以要怎么调用empty比呢?*/
	template<class T, class Alloc>
	deque<T, Alloc>::deque()
		:mapSize_(0), map_(0){
    
    }
	template<class T, class Alloc>
	deque<T, Alloc>::deque(size_type n, const value_type& val = value_type()){
    
    
		deque();
		deque_aux(n, val, typename std::is_integral<size_type>::type());
	}    
	template<class T, class Alloc>
	template <class InputIterator>
	deque<T, Alloc>::deque(InputIterator first, InputIterator last){
    
    
		deque();
		deque_aux(first, last, typename std::is_integral<InputIterator>::type());
	}

    /*上面三个初始化的问题都在少赋初值,而下面这个问题就大多了,首先连初始化都没有,就直接开始了?直接就到了getAnewMap去了?
    而且在这个过程中,并没有对deque成员变量的初始化。实际上这个初始化,明显可以调用
    deque_aux(x.begin(), x.end(), typename std::is_integral<InputIterator>::type())*/
	template<class T, class Alloc>
	deque<T, Alloc>::deque(const deque& x){
    
    
		mapSize_ = x.mapSize_;
		map_ = getANewMap(mapSize_);
		for (int i = 0; i + x.begin_.mapIndex_ != x.mapSize_; ++i)
			for (int j = 0; j != getBuckSize(); ++j)
				map_[x.begin_.mapIndex_ + i][j] = x.map_[x.begin_.mapIndex_ + i][j];
		begin_.mapIndex_ = x.begin_.mapIndex_;
		end_.mapIndex_ = x.end_.mapIndex_;
		begin_.cur_ = map_[begin_.mapIndex_] + (x.begin_.cur_ - x.map_[x.begin_.mapIndex_]);
		end_.cur_ = map_[end_.mapIndex_] + (x.end_.cur_ - x.map_[x.end_.mapIndex_]);
		begin_.container_ = end_.container_ = this;
	}


    //接口函数
    //后插
	template<class T, class Alloc>
	void deque<T, Alloc>::push_back(const value_type& val){
    
    
		if (empty()){
    
    
			init();
		}
		else if (back_full()){
    
    
			reallocateAndCopy();
		}
		//*end_ = val;
		//bug fix
		//2015.01.02
		TinySTL::construct(end_.cur_, val);//赋值
		++end_;//初始化的过程中end_根本就没有调用过,怎么自加?
	}
    //前插
	template<class T, class Alloc>
	void deque<T, Alloc>::push_front(const value_type& val){
    
    
		if (empty()){
    
    
			init();
		}
		else if (front_full()){
    
    
			reallocateAndCopy();
		}
		--begin_;
		//*begin_ = val;
		//bug fix
		//2015.01.02
		TinySTL::construct(begin_.cur_, val);
	}
    //前删
	template<class T, class Alloc>
	void deque<T, Alloc>::pop_front(){
    
    
		dataAllocator::destroy(begin_.cur_);
		++begin_;
	}
    //后删
	template<class T, class Alloc>
	void deque<T, Alloc>::pop_back(){
    
    
		--end_;
		dataAllocator::destroy(end_.cur_);
	}
    //清空
    template<class T, class Alloc>
	void deque<T, Alloc>::clear(){
    
    
		/*for (int i = 0; i != mapSize_; ++i)
		if (!map_[i])
		dataAllocator::destroy(map_[i], map_[i] + getBuckSize());*/
		for (auto i = 0; i != mapSize_; ++i){
    
    
			for (auto p = map_[i] + 0; !p && p != map_[i] + getBuckSize(); ++p)
				dataAllocator::destroy(p);
		}
		mapSize_ = 0;
		begin_.mapIndex_ = end_.mapIndex_ = mapSize_ / 2;
		begin_.cur_ = end_.cur_ = map_[mapSize_ / 2];
	}

    template<class T, class Alloc>
	void deque<T, Alloc>::swap(deque<T, Alloc>& x){
    
    
		TinySTL::swap(mapSize_, x.mapSize_);
		TinySTL::swap(map_, x.map_);
		begin_.swap(x.begin_);
		end_.swap(x.end_);
	}


    //**********************内部辅助函数***************************
    //重新申请内存转移
	template<class T, class Alloc>
	void deque<T, Alloc>::reallocateAndCopy(){
    
    
		auto newMapSize = getNewMapSize(mapSize_);
		T** newMap = getANewMap(newMapSize);
		size_t startIndex = newMapSize / 4;
		for (int i = 0; i + begin_.mapIndex_ != mapSize_; ++i)
			for (int j = 0; j != getBuckSize(); ++j)
				newMap[startIndex + i][j] = map_[begin_.mapIndex_ + i][j];

		size_t n = begin_.cur_ - map_[begin_.mapIndex_];
		auto size = this->size();
		auto b = begin_, e = end_;
		clear();
		mapSize_ = newMapSize;
		map_ = newMap;
		begin_ = iterator(startIndex, newMap[startIndex] + n, this);
		end_ = begin_ + size;
	}

    //看后边是不是满了
    template<class T, class Alloc>
	bool deque<T, Alloc>::back_full()const{
    
    
		return map_[mapSize_ - 1] && (map_[mapSize_]) == end().cur_;
	}
    //看前边是不是满了
	template<class T, class Alloc>
	bool deque<T, Alloc>::front_full()const{
    
    
		return map_[0] && map_[0] == begin().cur_;
	}
    //辅助插入。这个函数也存在很大的问题,因为是转化为前插和后插,所以如果都等到插入完了,才发现不够岂不是浪费空间和时间?
	template<class T, class Alloc>
	void deque<T, Alloc>::deque_aux(size_t n, const value_type& val, std::true_type){
    
    
		int i = 0;
		for (; i != n / 2; ++i)
			(*this).push_front(val);
		for (; i != n; ++i)
			(*this).push_back(val);
	}
	template<class T, class Alloc>
	template<class Iterator>
	void deque<T, Alloc>::deque_aux(Iterator first, Iterator last, std::false_type){
    
    
		difference_type mid = (last - first) / 2;
		for (auto it = first + mid; it != first - 1; --it)
			(*this).push_front(*it);
		for (auto it = first + mid + 1; it != last; ++it)
			(*this).push_back(*it);
	}
    //初始化
	template<class T, class Alloc>
	void deque<T, Alloc>::init(){
    
    
		mapSize_ = 2;//这个初始化为2,STL中为》=8
		map_ = getANewMap(mapSize_);//获取一个缓冲池
		begin_.container_ = end_.container_ = this;
		begin_.mapIndex_ = end_.mapIndex_ = mapSize_ - 1;//这个mapIndex设计的着实有点让人看不懂
		begin_.cur_ = end_.cur_ = map_[mapSize_ - 1];
	}
    //获取一个新的缓冲池
	template<class T, class Alloc>
	T *deque<T, Alloc>::getANewBuck(){
    
    
		return dataAllocator::allocate(getBuckSize());
	}
    //获取新的缓冲区
	template<class T, class Alloc>
	T** deque<T, Alloc>::getANewMap(const size_t size){
    
    
		T **map = new T*[size];
		for (int i = 0; i != size; ++i)
			map[i] = getANewBuck();
		return map;
	}
    //似乎没必要单独写一个函数,但写出来的好处是,不用修改重新申请内存的函数
	template<class T, class Alloc>
	size_t deque<T, Alloc>::getNewMapSize(const size_t size){
    
    
		return (size == 0 ? 2 : size * 2);
	}
    //缓冲池大小
	template<class T, class Alloc>
	size_t deque<T, Alloc>::getBuckSize()const{
    
    
		return (size_t)EBucksSize::BUCKSIZE;
	}


    //友元运算符和swap
	template <class T, class Alloc>
	bool operator== (const deque<T, Alloc>& lhs, const deque<T, Alloc>& rhs){
    
    
		auto cit1 = lhs.begin(), cit2 = rhs.begin();
		for (; cit1 != lhs.end() && cit2 != rhs.end(); ++cit1, ++cit2){
    
    
			if (*cit1 != *cit2)
				return false;
		}
		if (cit1 == lhs.end() && cit2 == rhs.end())
			return true;
		return false;
	}
	template <class T, class Alloc>
	bool operator!= (const deque<T, Alloc>& lhs, const deque<T, Alloc>& rhs){
    
    
		return !(lhs == rhs);
	}
	template <class T, class Alloc>
	void swap(deque<T, Alloc>& x, deque<T, Alloc>& y){
    
    
		x.swap(y);
	}
}
#endif

猜你喜欢

转载自blog.csdn.net/meixingshi/article/details/114290406