按书中给出的简化的代码编写的,省略了异常处理。
vs2012编译时候会报告警,是copy操作的越界告警,虽然没影响,估计要修改下编码方式来解决。
//自行加入reserve函数的实现
#ifndef vector_H_ #define vector_H_ #include "allocator.h" namespace SGISTL { template<typename T, typename Alloc = SGISTL::alloc> class vector { public: typedef T value_type; typedef value_type* pointer; typedef value_type* iterator; typedef value_type& reference; typedef size_t size_type; typedef ptrdiff_t difference_type; protected: typedef simple_alloc<value_type, alloc> data_allocator; iterator start; iterator finish; iterator end_of_storage; protected: void insert_aux(iterator position, const T& x) { if(finish != end_of_storage) //感觉这里可以再细分成2个函数,一个处理已分配的空间足够,一个处理已分配的空间不足 { construct(finish, *(finish - 1)); ++finish; std::copy_backward(position, finish - 2, finish - 1); *position = std::move(x); } else { const size_type old_size = size(); const size_type new_size = (old_size != 0 ? old_size * 2 : 1); iterator new_start = data_allocator::allocate(new_size); iterator new_finish = new_start; //省略异常处理 new_finish = SGISTL::uninitialized_copy(start, position, new_start); construct(new_finish, x); ++new_finish; new_finish = SGISTL::uninitialized_copy(position, finish, new_finish); destroy(start, finish); deallocate(); start = new_start; finish = new_finish; end_of_storage = start + new_size; } } void deallocate() { if(start != nullptr) { data_allocator::deallocate(start, end_of_storage - start); } } void fill_initialize(size_type n, const T& value) { start = allocate_and_fill(n, value); finish = start + n; end_of_storage = finish; } iterator allocate_and_fill(size_type n, const T& value) { iterator result = data_allocator::allocate(n); SGISTL::uninitialized_fill_n(result, value); return result; } public: vector(): start(nullptr), finish(nullptr), end_of_storage(nullptr) { } vector(size_type n, const T& value) { fill_initialize(n, value); } explicit vector(size_type n) { fill_initialize(n, T()); } ~vector() { destroy(start, finish); deallocate(); } reference operator[](size_type n) { return *(begin() + n); } public: iterator begin() { return start; } iterator end() { return finish; } const iterator cbegin()const { return start; } const iterator cend()const { return finish; } size_type size()const { return static_cast<size_type>(finish - start); } size_type capacity()const { return static_cast<size_type>(end_of_storage - start); } bool empty()const { return start == finish; } reference front() { return *(begin()); } reference back() { return *(finish - 1); } void push_back(const T& value) { if(finish != end_of_storage) { construct(finish, value); ++finish; } else { insert_aux(finish, value); } } void pop_back() { --finish; destroy(finish); } iterator erase(iterator postion) { if((postion + 1) != end) { std::copy(postion + 1, finish, postion); } --finish; destroy(finish); return postion; } iterator erase(iterator first, iterator last) { iterator iter = std::copy(last, finish, first); destroy(iter, finish); finish = finish - (last - first); return first; } void resize(size_type new_size, const T& value) { if(new_size < size()) { erase(begin() + new_size, finish); } else { insert(end(), new_size - size(), value); } } void resize(size_type new_size) { resize(new_size, T()); } void clear() { erase(start, finish); }; void insert(iterator position, size_type n, const T& value) { if(n == 0) { return; } if(static_cast<size_type>(end_of_storage - finish) >= n) { const size_type elems_after = finish - position; iterator old_finish = finish; if(elems_after > n) { SGISTL::uninitialized_copy(finish - n, finish, finish); finish += n; std::copy_backward(position, old_finish - n, old_finish); std::fill(position, position + n, value); } else { uninitialized_fill_n(finish, n - elems_after, value); finish += n - elems_after; uninitialized_copy(position, old_finish, finish); finish += elems_after; std::fill(position, old_finish, value); } } else { const size_type old_size = size(); const size_type new_size = old_size + max(old_size, n); iterator new_start = data_allocator::allocate(new_size); iterator new_finish = new_start; new_finish = SGISTL::uninitialized_copy(start, position, new_start); new_finish = SGISTL::uninitialized_fill_n(new_finish, n, value); new_finish = SGISTL::uninitialized_copy(position, finish, new_finish); destroy(start, finish); deallocate(); start = new_start; finish = new_finish; end_of_storage = start + new_size; }; }; void reserve(size_type n) { if(static_cast<size_type>(end_of_storage - start) < n) { iterator new_start = data_allocator::allocate(n); iterator new_finish = new_start; new_finish = SGISTL::uninitialized_copy(start, finish, new_start); destroy(start, finish); deallocate(); start = new_start; finish = new_finish; end_of_storage = start + n; } } }; }; #endif