stl源码剖析 第四章vector实现

来源:互联网 发布:sql unique 约束 编辑:程序博客网 时间:2024/06/06 19:31
template<typename T, typename Alloc = alloc>class vec{public:typedef T value_type;typedef T* point;typedef T* iter;typedef T& refer;typedef size_t size_type;protected:typedef simple_alloc<value_type, Alloc> data_allocator;iter start;iter first_free;iter end_of_storage;void insert_aux(iter pos, const T& x);void deallocate();void fill_initialized(size_type n, const T& x);public:vec() :start(0), first_free(0), end_of_storage(0) {}vec(size_type n, const T& x) { fill_initialized(n, x); }vec(int n, const T& x) { fill_initialized(n, x); }vec(long n, const T& x) { fill_initialized(n, x); }explicit vec(size_type n) { fill_initialized(n, T()); }~vec();iter begin() { return start; }iter end() { return first_free; }size_type size() const { return first_free - start; }size_type capacity() const { return end_of_storage - start; }bool empty() { return begin == end; }refer operator[](size_type n) { return *(begin + n); }refer front() { return *begin(); }refer bcak() { return *(end() - 1); }void push_back(const T& x);void pop_back();iter erase(iter pos);iter erase(iter first, iter second);void resize(size_type new_size, const T& x);void resize(size_type new_size);void clear();void insert(iter pos, const T& x) { insert_aux(pos, x); }void insert(iter pos, size_type n, const T& x);protected:iter alloc_and_fill(size_type n, const T& x);};template<typename T, typename Alloc>void vec<T, Alloc>::insert_aux(iter pos, const T& x){if (first_free != end_of_storage){construct(first_free, *(first_free - 1));++first_free;std::copy_backward(pos, first_free - 2, first_free - 1);*pos = x;}else{const size_type old_size = size();const size_type new_size = old_size == 0 ? 1 : old_size * 2;iter new_start = Alloc::allocate(new_size);iter new_first_free = new_start;try{new_first_free = std::uninitialized_copy(start, first_free, new_start);construct(new_first_free, x);++new_first_free;}catch (...){std::_Destroy(new_start, new_first_free);deallocate(new_start, new_size);throw;}std::_Destroy(begin(), end());deallocate();start = new_start;first_free = new_first_free;end_of_storage = start + new_size;}}template<typename T, typename Alloc>void vec<T, Alloc>::deallocate(){if (start)data_allocator::deallocate(start, end_of_storage-start);}template<typename T, typename Alloc>void vec<T, Alloc>::fill_initialized(size_type n, const T& x){start = alloc_and_fill(n, x);first_free = start + n;end_of_storage = first_free;}template<typename T, typename Alloc>vec<T, Alloc>::~vec(){destroy(start, first_free);deallocate();}template<typename T, typename Alloc>void vec<T, Alloc>::push_back(const T& x){if (first_free != end_of_storage){construct(first_free, x);++first_free;}elseinsert_aux(end(), x);}template<typename T, typename Alloc>void vec<T, Alloc>::pop_back(){--first_free;destroy(first_free);}template<typename T, typename Alloc>typename vec<T, Alloc>::iter vec<T, Alloc>::erase(iter pos){if (pos + 1 != end())std::copy(pos + 1, first_free, pos);--first_free;destroy(first_free);return pos;}template<typename T, typename Alloc>typename vec<T, Alloc>::iter vec<T, Alloc>::erase(iter first, iter second){iter i = copy(second + 1, first_free, first);destroy(i, first_free);first_free = first_free - (second - first);// first_free == i   ?return first;}template<typename T, typename Alloc>void vec<T, Alloc>::resize(size_type new_size, const T& x){if (new_size < size())eraser(begin() + new_size, end());elseinsert(end(end(), new_size - size(), x));}template<typename T, typename Alloc>void vec<T, Alloc>::resize(size_type new_size){resize(new_size, T());}template<typename T, typename Alloc>void vec<T, Alloc>::insert(iter pos, size_type n, const T& x){if (n>0){if (size_type(end_of_storage - first_free) >= n){const size_type elems_after = first_free - pos;iter old_first_free = first_free;if (elems_after > n){std::uninitialized_copy(first_free - n, first_free, first_free);std::copy_backward(pos, first_free - n, first_free);first_free += n;std::fill(pos, pos + n, x);}else{std::uninitialized_fill_n(first_free, n - elems_after, x);first_free += (n - elems_after);std::uninitialized_copy(pos, old_first_free, first_free);first_free += elems_after;std::fill(pos, old_first_free, x);}}else{const size_type old_size = size();const size_type new_size = old_size + std::max(old_size, n);iter new_start = Alloc::allocate(new_size);iter new_first_free = new_start;try{new_first_free = std::uninitialized_copy(start, pos, new_start);new_first_free = std::uninitialized_fill_n(new_first_free, n, x);new_first_free = std::uninitialized_copy(pos, first_free, new_first_free);}#ifdef  _STL_USE_EXCEPTIONScatch (...){destroy(new_start, new_first_free);data_allocator::deallocate(new_start, new_size);throw;}#endifdestroy(begin(), end());deallocate();start = new_start;first_free = new_first_free;end_of_storage = start + new_size;}}}template<typename T, typename Alloc>void vec<T, Alloc>::clear(){eraser(begin(), end());}template<typename T, typename Alloc>typename vec<T, Alloc>::iter vec<T, Alloc>::alloc_and_fill(size_type n, const T& x){iter ret = data_allocator::allocate(n);std::uninitialized_fill_n(ret, n, x);return ret;}


标准stl的allocator接口

http://www.cplusplus.com/reference/memory/allocator/




sgi stl

construct() 和destroy()是一个全局函数,其中destroy有两个版本,接受一个指针或者一对迭代器。

它的空间配置器alloc和标准规范不同,不接受任何参数。(现在不知道是不是还是这样)

可以给它包装一下,从而符合规范。

template<typename T, typename Alloc>class simple_alloc{public:static T* allocate(size_t n){return n==0? 0:(T*)Alloc::allocate(n * sizeof(T));}static T* allocate(void){return (T*)Alloc::allocate(sizeof(T));}static void deallocate(T* p, size_t n){if(n)Alloc::deallocate(p, n*sizeof(T));}static void deallocate(T* p){Alloc::dealloccate(p, sizeof(T));}};

sgi stl里有一个符合标准的allocator,但是不推荐使用,只是对::operator new 和::operator delete的一层包装而已。

#ifndef DEFALLOC_H#define DEFALLOC_H#include<new.h>#include<stddef.h>#include<stdlib.h>#include<limits.h>#include<iostream>#include<algobase.h>template<typename T>inline T* allocate(ptrdiff_t size, T*){T* temp = (T*) (::operator new( (size_t)(size*sizeof(T) )));if(temp == 0){std::cerr<<"out of memory"<<std::endl;exit(1);}return temp;}template<typename T>inline T* deallocate(T* buffer){::operator delete(buffer);}template<typename T>class allocator{public:typedef T value_type;typedef T* point;typedef const T* const_point;typedef T* iter;typedef T& refer;typedef const T& const_refer; typedef size_t size_type;typedef ptrdiff_t difference_type;point allocate(size_type n){return ::allocate( (difference_type)n, (point)0 );}void deallcate(point p){::deallocate(p);}point address(refer x){return (point)&x;}const_point const_address(const_refer x){return (const_point)&x;}size_type init_page_size(){return std::max(size_type(1), size_type(4096)/sizeof(T));}size_type max_size() const{return std::max(size_type(1), size_type(UNIT_MAX/sizeof(T)) );}};

原创粉丝点击