tinystl实现(第二十六步:circularbuffer实现)

39 篇文章 4 订阅
28 篇文章 36 订阅

经过长时间的学习终于可以开始tinystl的仿(chao)写工作了,本文参考了这位大神的github,坦白讲我只是补充了注释,因为tinystl的代码真的非常经典而我又没什么这种大型项目的经验,所以只能这样做,不过相信能够有助于大家的学习
#强烈建议按顺序阅读本专栏
circularbuffer,中文名环状数组,当存储超出范围时会从头开始存储(覆盖之前的数据)的数组,其实现并不困难。
.h文件

#pragma once
#ifndef _CIRCULATR_BUFFER_H_
#define _CIRCULATR_BUFFER_H_
#include "Allocator.h"
#include "Iterator.h"
#include "UninitializedFunctions.h"

#include <cassert>

namespace mySTL {
	template<class T, size_t N, class Alloc>
	class circular_buffer;
	namespace Detail {
		//the iterator of circular buffer
		template<class T, size_t N, class Alloc = allocator<T>>
		class cb_iter :iterator<bidirectional_iterator_tag, T> {//bidirectional iterator
		private:
			typedef ::mySTL::circular_buffer<T, N, Alloc> cb;
			typedef cb *cbPtr;

			T *ptr_;
			int index_;
			cbPtr container_;
		public:
			cb_iter() :ptr_(0), index_(0), container_(0) {}
			cb_iter(T *ptr, cbPtr container) :
				ptr_(ptr), index_(ptr - container->start_), container_(container) {}
			cb_iter(const cb_iter& cit) :
				ptr_(cit.ptr_), index_(cit.index_), container_(cit.container_) {}
			cb_iter& operator = (const cb_iter& cit);
		public:
			operator T*() { return ptr_; }
			T& operator *() { return *ptr_; }
			T *operator ->() { return &(operator*()); }

			cb_iter& operator ++();
			cb_iter operator ++(int);
			cb_iter& operator --();
			cb_iter operator --(int);
			bool operator == (const cb_iter& it)const;
			bool operator != (const cb_iter& it)const;
		private:
			void setIndex_(int index) { index_ = index; }
			void setPtr_(T *ptr) { ptr_ = ptr; }
			int nextIndex(int index) { return (++index) % N; }
			int prevIndex(int index);
		public:
			template<class T, size_t N, class Alloc>
			friend cb_iter<T, N, Alloc> operator +(const cb_iter<T, N, Alloc>& cit, std::ptrdiff_t i);
			template<class T, size_t N, class Alloc>
			friend cb_iter<T, N, Alloc> operator -(const cb_iter<T, N, Alloc>& cit, std::ptrdiff_t i);
		};
	}//end of Detail namespace

	//circular buffer
	template<class T, size_t N, class Alloc = allocator<T>>
	class circular_buffer {
		template<class T, size_t N, class Alloc>
		friend class ::mySTL::Detail::cb_iter;
	public:
		typedef T				value_type;
		typedef Detail::cb_iter<T, N>	iterator;
		typedef iterator		pointer;
		typedef T&				reference;
		typedef int				size_type;
		typedef ptrdiff_t		difference_type;
	private:
		T *start_;
		T *finish_;
		int indexOfHead;//the first position
		int indexOfTail;//the last position 
		size_type size_;

		typedef Alloc dataAllocator;
	public:
		explicit circular_buffer(const int& n, const value_type& val = value_type());
		template<class InputIterator>
		circular_buffer(InputIterator first, InputIterator last);
		circular_buffer(const circular_buffer& cb);
		circular_buffer& operator = (const circular_buffer& cb);
		circular_buffer& operator = (circular_buffer&& cb);
		circular_buffer(circular_buffer&& cb);
		~circular_buffer();

		bool full() { return size_ == N; }
		bool empty() { return size_ == 0; }
		difference_type capacity() { return finish_ - start_; }
		size_type size() { return size_; }
		void clear();

		iterator first() { return iterator(start_ + indexOfHead, this); }
		iterator last() { return iterator(start_ + indexOfTail, this); }

		reference operator [](size_type i) { return *(start_ + i); }
		reference front() { return *(start_ + indexOfHead); }
		reference back() { return *(start_ + indexOfTail); }
		void push_back(const T& val);
		void pop_front();

		bool operator == (circular_buffer& cb);
		bool operator != (circular_buffer& cb);

		Alloc get_allocator() { return dataAllocator; }
	private:
		void allocateAndFillN(const int& n, const value_type& val);
		template<class InputIterator>
		void allocateAndCopy(InputIterator first, InputIterator last);
		int nextIndex(int index) { return (index + 1) % N; }
		void copyAllMembers(const circular_buffer& cb);
		void zeroCircular(circular_buffer& cb);
		void clone(const circular_buffer& cb);
	public:
		template<class T, size_t N, class Alloc>
		friend std::ostream& operator <<(std::ostream& os, circular_buffer<T, N, Alloc>& cb);
	};//end of circular buffer
}

#include "Detail\CircularBuffer.impl.h"
#endif

impl.h文件

#pragma once
#ifndef  _CIRCULAR_BUFFER_IMPL_H_
#define _CIRCULAR_BUFFER_IMPL_H_
namespace mySTL {
	namespace Detail {
		//如果前方超出范围则返回后方位置
		template<class T, size_t N, class Alloc>
		int cb_iter<T, N, Alloc>::prevIndex(int index) {
			--index;
			index = (index == -1 ? index + N : index);
			return index;
		}
		//判断相等
		template<class T, size_t N, class Alloc>
		bool cb_iter<T, N, Alloc>::operator == (const cb_iter& it)const {
			return (container_ == it.container_) &&
				(ptr_ == it.ptr_) && (index_ == it.index_);
		}
		template<class T, size_t N, class Alloc>
		bool cb_iter<T, N, Alloc>::operator != (const cb_iter& it)const {
			return !((*this) == it);
		}
		//借助nextindex完成++
		template<class T, size_t N, class Alloc>
		cb_iter<T, N, Alloc>& cb_iter<T, N, Alloc>::operator ++() {
			setIndex_(nextIndex(index_));
			setPtr_(container_->start_ + index_);
			return *this;
		}
		template<class T, size_t N, class Alloc>
		cb_iter<T, N, Alloc> cb_iter<T, N, Alloc>::operator ++(int) {
			cb_iter temp(*this);
			++(*this);
			return temp;
		}
		//借助previndex完成--
		template<class T, size_t N, class Alloc>
		cb_iter<T, N, Alloc>& cb_iter<T, N, Alloc>::operator --() {
			setIndex_(prevIndex(index_));
			setPtr_(container_->start_ + index_);
			return *this;
		}
		template<class T, size_t N, class Alloc>
		cb_iter<T, N, Alloc> cb_iter<T, N, Alloc>::operator --(int) {
			cb_iter temp(*this);
			--(*this);
			return temp;
		}
		//相等
		template<class T, size_t N, class Alloc>
		cb_iter<T, N, Alloc>& cb_iter<T, N, Alloc>::operator = (const cb_iter& cit) {
			if (this != &cit) {
				ptr_ = cit.ptr_;
				index_ = cit.index_;
				container_ = cit.container_;
			}
			return *this;
		}
		//+的值可能是负数
		template<class T, size_t N, class Alloc>
		cb_iter<T, N, Alloc> operator +(const cb_iter<T, N, Alloc>& cit, std::ptrdiff_t i) {
			int real_i = i % (std::ptrdiff_t)N;//assume i >= 0
			if (real_i < 0)
				real_i += N;
			cb_iter<T, N, Alloc> res = cit;
			res.setIndex_(res.index_ + real_i);
			res.setPtr_(res.ptr_ + res.index_);
			return res;
		}
		template<class T, size_t N, class Alloc>
		cb_iter<T, N, Alloc> operator -(const cb_iter<T, N, Alloc>& cit, std::ptrdiff_t i) {
			cb_iter<T, N, Alloc> res = cit;
			return (res + (-i));
		}
	}
	//**********构造,复制,析构相关*****************
	//析构
	template<class T, size_t N, class Alloc>
	circular_buffer<T, N, Alloc>::~circular_buffer() {
		clear();
		dataAllocator::deallocate(start_, size_);
	}
	//
	template<class T, size_t N, class Alloc>
	circular_buffer<T, N, Alloc>::circular_buffer(const int& n, const value_type& val = value_type()) {
		assert(n != 0);
		allocateAndFillN(n, val);
	}
	template<class T, size_t N, class Alloc>
	template<class InputIterator>
	circular_buffer<T, N, Alloc>::circular_buffer(InputIterator first, InputIterator last) {
		//bug fix
		//2015.01.05
		assert(first != last);
		allocateAndCopy(first, last);
	}
	template<class T, size_t N, class Alloc>
	circular_buffer<T, N, Alloc>::circular_buffer(const circular_buffer<T, N, Alloc>& cb) {
		clone(cb);
	}
	template<class T, size_t N, class Alloc>
	circular_buffer<T, N, Alloc>::circular_buffer(circular_buffer<T, N, Alloc>&& cb) {
		copyAllMembers(cb);
		zeroCircular(cb);
	}
	template<class T, size_t N, class Alloc>
	circular_buffer<T, N, Alloc>& circular_buffer<T, N, Alloc>::operator = (const circular_buffer<T, N, Alloc>& cb) {
		if (this != &cb) {
			clone(cb);
		}
		return *this;
	}
	template<class T, size_t N, class Alloc>
	circular_buffer<T, N, Alloc>& circular_buffer<T, N, Alloc>::operator = (circular_buffer<T, N, Alloc>&& cb) {
		if (*this != cb) {
			copyAllMembers(cb);
			zeroCircular(cb);
		}
		return *this;
	}
	//添加
	template<class T, size_t N, class Alloc>
	void circular_buffer<T, N, Alloc>::push_back(const T& val) {
		if (full()) {//是否填满就算+不+size的问题
			indexOfTail = nextIndex(indexOfTail);
			dataAllocator::construct(start_ + indexOfTail, val);
			indexOfHead = nextIndex(indexOfHead);
		}
		else {
			indexOfTail = nextIndex(indexOfTail);
			dataAllocator::construct(start_ + indexOfTail, val);
			++size_;
		}
	}
	//从前方排除
	template<class T, size_t N, class Alloc>
	void circular_buffer<T, N, Alloc>::pop_front() {
		if (empty())
			throw;
		dataAllocator::destroy(start_ + indexOfHead);
		indexOfHead = nextIndex(indexOfHead);
		--size_;
	}
	//输出用括号括起,逗号分隔,用size停止,it移动
	template<class T, size_t N, class Alloc>
	std::ostream& operator <<(std::ostream& os, circular_buffer<T, N, Alloc>& cb) {
		circular_buffer<T, N, Alloc>::size_type size = cb.size();
		if (!cb.empty()) {
			os << "(";
			for (auto it = cb.first(); it != cb.last() && size != 0; ++it, --size) {
				os << *it << ", ";
			}
			os << *(cb.last()) << ")";
		}
		return os;
	}
	//逐个destroy
	template<class T, size_t N, class Alloc>
	void circular_buffer<T, N, Alloc>::clear() {
		for (; !empty(); indexOfHead = nextIndex(indexOfHead), --size_) {
			dataAllocator::destroy(start_ + indexOfHead);
		}
		indexOfHead = indexOfTail = 0;
	}
	//大同小异的相等
	template<class T, size_t N, class Alloc>
	bool circular_buffer<T, N, Alloc>::operator == (circular_buffer& cb) {
		auto it1 = first(), it2 = cb.first();
		for (; it1 != last() && it2 != cb.last(); ++it1, ++it2) {
			if (*it1 != *it2) return false;
		}
		return (it1 == last()) && (it2 == cb.last()) && (*(last()) == *(cb.last()));
	}
	template<class T, size_t N, class Alloc>
	bool circular_buffer<T, N, Alloc>::operator != (circular_buffer& cb) {
		return !(*this == cb);
	}
	template<class T, size_t N, class Alloc>
	void circular_buffer<T, N, Alloc>::allocateAndFillN(const int& n, const value_type& val) {//only for ctor
		start_ = dataAllocator::allocate(N);
		finish_ = start_ + N;
		indexOfHead = 0;
		if (N <= n) {
			finish_ = TinySTL::uninitialized_fill_n(start_, N, val);
			indexOfTail = N - 1;
			size_ = N;
		}
		else {//N > n
			finish_ = TinySTL::uninitialized_fill_n(start_, n, val);
			finish_ = TinySTL::uninitialized_fill_n(finish_, N - n, value_type());
			indexOfTail = n - 1;
			size_ = n;
		}
	}
	//改变存储位置的复制
	template<class T, size_t N, class Alloc>
	template<class InputIterator>
	void circular_buffer<T, N, Alloc>::allocateAndCopy(InputIterator first, InputIterator last) {//only for ctor
		int n = last - first;
		start_ = dataAllocator::allocate(N);
		indexOfHead = 0;
		if (N <= n) {
			finish_ = mySTL::uninitialized_copy(first, first + N, start_);
			indexOfTail = N - 1;
			size_ = N;
		}
		else {//N > n多余部分舍去
			finish_ = mySTL::uninitialized_copy(first, last, start_);
			finish_ = mySTL::uninitialized_fill_n(finish_, N - n, value_type());
			indexOfTail = n - 1;
			size_ = n;
		}
	}
	//不改变内存位置的复制
	template<class T, size_t N, class Alloc>
	void circular_buffer<T, N, Alloc>::copyAllMembers(const circular_buffer& cb) {
		start_ = cb.start_;
		finish_ = cb.finish_;
		indexOfHead = cb.indexOfHead;
		indexOfTail = cb.indexOfTail;
		size_ = cb.size_;
	}
	//归零
	template<class T, size_t N, class Alloc>
	void circular_buffer<T, N, Alloc>::zeroCircular(circular_buffer& cb) {
		cb.start_ = cb.finish_ = 0;
		cb.indexOfHead = cb.indexOfTail = cb.size_ = 0;
	}
	//复制
	template<class T, size_t N, class Alloc>
	void circular_buffer<T, N, Alloc>::clone(const circular_buffer& cb) {
		start_ = dataAllocator::allocate(N);
		finish_ = start_ + N;
		size_ = N;
		indexOfHead = cb.indexOfHead;
		indexOfTail = cb.indexOfTail;
		mySTL::uninitialized_copy(cb.start_, cb.finish_, start_);
	}
}
#endif // ! _CIRCULAR_BUFFER_IMPL_H_

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值