ZSL_Vector
最近事情太多了,是在没时间更新,刚好最近也在读标准库源码,其实开始已经写过自己的string类,但是发现和标准库相差甚远,所以会重新写一下,这次花了两个小时不到模仿了标准库的vector,可能内部实现方式有点点不一样,因为标准库是把对象构造和析构,空间的配置和销毁是分开的,因为我看的SGI的STL,空间配置器那部分涉及太多内存操作,包括内存池等,这都是需要很深厚的功力才能完成,学生狗一只就不准备模仿了。
这次的代码,主要参考了:cppreference,SGI STL2.9版本,STL源码剖析书。
注:暂时只测试了一部分,后续会慢慢更新
—————————————————————————————————————————
#ifndef __ZSL_Vector_H__ #define __ZSL_Vector_H__ #include <iostream> #include <algorithm> using namespace std; template<typename T> class ZSL_Vector { public: using value_type = T; using pointer = value_type*; using const_pointer = const value_type*; using iterator = value_type*; using const_iterator = const value_type*; using reference = value_type&; using const_reference = const value_type&; using size_type = size_t; using difference_type = ptrdiff_t; private: iterator start; iterator finish; iterator end_of_storage; private: pointer allocate(size_t n) { return (pointer)malloc(n * sizeof(T)); } void construct(pointer p, const value_type& value) { new(p)value_type(value); } void destroy_aux(pointer p) { p->~T(); } void destroy(pointer first, pointer last) { while(first != last){ destroy_aux(first); ++first; } } void deallocate() { if(start) free(start); } iterator uninitialized_copy(iterator first, iterator last, iterator res){ while(first < last){ construct(res, *first); ++first; ++res; } return res + (last - first); } iterator copy(iterator first, iterator last, iterator res){ while(first < last){ *res = *first; ++first, ++res; } return res + (last - first); } void uninitialized_fill(size_t n, const T& value){ start = allocate(n); finish = start + n; for(int i = 0; i < n; ++i) construct(start + i, value); end_of_storage = finish; } void fill(iterator first, iterator last, const value_type& value){ while(first != last){ *first = value; ++first; } } void refill(const ZSL_Vector<T>& rhs){ start = allocate(rhs.size()); uninitialized_copy(rhs.start, rhs.finish, start); finish = start + rhs.size(); end_of_storage = finish; } void copy_backward(iterator first, iterator last, iterator it){ while(last != first){ *it = *last; --last; --it; } } void insert_aux(iterator pos, const T& value); void erase_aux1(iterator pos); void erase_aux2(iterator pos1, iterator pos2){ iterator new_finish = uninitialized_copy(pos2, finish, pos1); destroy(new_finish, finish); finish = new_finish; } public: ZSL_Vector() : start(0), finish(0), end_of_storage(0) {} ZSL_Vector(size_t n, const T& value) { uninitialized_fill(n, value); } ZSL_Vector(size_t n) { uninitialized_fill(n, T()); } ZSL_Vector(const T& value) { uninitialized_fill(1, value); } ZSL_Vector(iterator first, iterator last){ auto ptr = first; for(; first != last; ++first) push_back(*first); } ZSL_Vector(const ZSL_Vector<T> &rhs){ refill(rhs); } ZSL_Vector<T>& operator = (const ZSL_Vector<T> &rhs){ if(this != &rhs){ if(rhs.size() > capacity()){ iterator new_start = allocate(rhs.size()); uninitialized_copy(rhs.cbegin(), rhs.cend(), new_start); destroy(start, finish); deallocate(); start = new_start; end_of_storage = finish; } else if(size() >= rhs.size()){ iterator tmp = copy(rhs.begin(), rhs.end(), begin()); destroy(tmp, finish); } else{ } finish = start + rhs.size(); } return *this; } ~ZSL_Vector(){ destroy(start, finish); deallocate(); } void assign( size_type count, const T& value ){ if(count <= size()){ erase(end() - count, end()); finish -= count; fill(begin(), end(), value); } else if(count <= capacity()){ finish += count; fill(begin(), end(), value); } else{ fill(begin(), end(), value); insert(end(), count, value); } } void assign(initializer_list<T> ilist){ size_type len = ilist.size(); if(len <= size()){ erase(end() - len, end()); finish -= len; copy(ilist.begin(), ilist.end(), begin()); } else if(len <= capacity()){ copy(ilist.begin(), ilist.begin() + size(), begin()); finish = uninitialized_copy(ilist.begin() + size(), ilist.end(), finish); } else{ copy(ilist.begin(), ilist.begin() + size(), begin()); insert(end(), ilist.begin() + size(), ilist.end()); } } reference at(size_type pos){ if(pos >= size()) throw "out_of_range"; return *(start + pos); } const_reference at(size_type pos) const { return const_cast<reference>(static_cast<ZSL_Vector<T>>(*this).start[pos]); } reference operator[](size_type pos){ return *(start + pos); } const_reference operator[](size_type pos) const { return *(start + pos); } reference front() { return *begin(); } const_reference front() const { return *begin(); } reference back() { return *(end() - 1); } const_reference back() const { return *(end() - 1); } iterator begin() { return start; } const_iterator cbegin() const { return start; } iterator end() { return finish; } const_iterator cend() const { return finish; } bool empty() const { return finish == 0; } size_type size() const { return finish - start; } size_type max_size() const { return size_type(-1)/sizeof(value_type); } pointer data() noexcept { return (pointer)start; } const_pointer data() const noexcept { return (const_pointer)start; } void reserve(size_type n){ if (n < size()) erase(begin() + n, end()); else insert(end(), n, T()); } size_type capacity() const { return end_of_storage - start; } void clear(){ erase(begin(), end()); } iterator insert(iterator pos, const T& value){ size_type n = pos - begin(); if(finish != end_of_storage && pos == end()){ construct(finish, value); ++finish; } else insert_aux(pos, value); return begin() + n; } iterator insert(const_iterator pos, const T& value){ size_type n = pos - begin(); if(finish != end_of_storage && pos == end()){ construct(finish, value); ++finish; } else insert_aux(pos, value); return begin() + n; } iterator insert( const_iterator pos, T&& value ){ insert(pos, value); } void insert( iterator pos, size_type count, const T& value ); /* iterator insert( const_iterator pos, size_type count, const T& value ); template< class InputIt > void insert( iterator pos, InputIt first, InputIt last); template< class InputIt > iterator insert( const_iterator pos, InputIt first, InputIt last ); iterator insert( const_iterator pos, std::initializer_list<T> ilist ); */ iterator erase(iterator pos){ if(pos + 1 != end()) copy(pos + 1, end(), pos); --finish; destroy_aux(finish); return pos; } iterator erase(const_iterator pos){ if(pos + 1 != end()) copy(pos + 1, end(), pos); --finish; destroy_aux(finish); return pos; } iterator erase(iterator first, iterator last){ iterator tmp = copy(last, finish, first); destroy(tmp, finish); finish = finish - (last - first); return first; } iterator erase(const_iterator first, const_iterator last){ iterator tmp = copy(last, finish, first); destroy(tmp, finish); finish = finish - (last - first); return first; } void push_back(const T& value) { if(finish != end_of_storage){ construct(finish, value); ++finish; } else insert_aux(end(), value); } void pop_back() { --finish; destroy_aux(finish); } void swap(ZSL_Vector& other){ using std::swap; swap(start, other.start); swap(finish, other.finish); swap(end_of_storage, other.end_of_storage); } }; template<typename T> bool operator == (const ZSL_Vector<T>& lhs, const ZSL_Vector<T>& rhs) { for(auto i = lhs.cbegin(), j = rhs.cbegin(); i != lhs.cend() && j != rhs.cend(); ++i, ++j) if(*i != *j) return false; return lhs.size() == rhs.size(); } template<typename T> bool operator != (const ZSL_Vector<T>& lhs, const ZSL_Vector<T>& rhs) { return !(lhs == rhs); } template<typename T> bool operator < (const ZSL_Vector<T>& lhs, const ZSL_Vector<T>& rhs) { for(auto i = lhs.cbegin(), j = rhs.cbegin(); i != lhs.cend() && j != rhs.cend(); ++i, ++j) if(*i >= *j) return false; return lhs.size() < rhs.size(); } template<typename T> bool operator <= (const ZSL_Vector<T>& lhs, const ZSL_Vector<T>& rhs) { for(auto i = lhs.cbegin(), j = rhs.cbegin(); i != lhs.cend() && j != rhs.cend(); ++i, ++j) if(*i > *j) return false; return lhs.size() < rhs.size(); } template<typename T> bool operator > (const ZSL_Vector<T>& lhs, const ZSL_Vector<T>& rhs) { return !(lhs <= rhs); } template<typename T> bool operator >= (const ZSL_Vector<T>& lhs, const ZSL_Vector<T>& rhs) { return !(lhs < rhs); } template<typename T> void ZSL_Vector<T>::insert_aux(iterator pos, const T& value) { if(finish != end_of_storage){ construct(finish, *(finish - 1)); ++finish; copy_backward(pos, finish - 2, finish - 1); *pos = value; } else{ const size_type old_size = size(); const size_type len = old_size == 0 ? 1 : (2 * old_size); iterator new_start = allocate(len); iterator new_finish = new_start; new_finish = uninitialized_copy(begin(), pos, new_finish); construct(new_finish, value); ++new_finish; new_finish = uninitialized_copy(pos, end(), new_finish); destroy(begin(), end()); deallocate(); start = new_start; finish = new_finish; end_of_storage = start + len; } } template<typename T> void ZSL_Vector<T>::insert( iterator pos, size_type count, const T& value ){ if(count != 0){ if(end_of_storage - finish >= count){ const size_type elems_after = finish - pos; iterator old_finish = finish; if(elems_after > count){ uninitialized_copy(finish - count, finish, finish); finish += count; copy_backward(pos, old_finish - count, old_finish); fill(pos, pos + count, value); } else{ size_type len = count - elems_after; while(len--){ *finish = value; ++finish; } uninitialized_copy(pos, pos + count, finish); finish += elems_after; fill(pos, pos + count, value); } } else{ const size_type old_size = size(); const size_type len = old_size + std::max(old_size, count); iterator new_start = allocate(len); iterator new_finish = new_start; new_finish = uninitialized_copy(start, pos, new_start); while(count--){ *new_finish = value; ++new_finish; } new_finish = uninitialized_copy(pos, finish, new_finish); destroy(start, finish); deallocate(); start = new_start; finish = new_finish; end_of_storage = new_start + len; } } } #endif //!__ZSL_Vector_H__