本文参考了侯捷的 《STL 源码分析》一书,出于兴趣,自行实现了简单的 vector 容器。
之后会陆续上传 list, deque 等容器的代码,若有错误,欢迎留言指出。
vector 容易实现的几点注意事项:
1. 由于vector 是动态数组。
出于效率的考虑,在往vector 中加入元素时,内存的扩展遵循的规则是:
1> 如果当前可用内存不够,开 2倍大的内存,将原来的数组复制到新数组中,撤销原来的数组。
2> 加入新的元素
2. 通常当我们 int *p = new int(1)时, new 其实做了两件事情: 1> 分配内存 2>在分配的内存中调用类的构造函数。
出于效率的考虑,在 vector 的内存管理中,我们将这两个操作分开。
C++ 提供了 模板类 allocator 来实现上述的功能。
3. vector 中三个指针,分别是 start, finish, end_of_storage;
[start, finish) 就是数组元素;
[finish, end_of_storage) 是预先分配的空间(还没有调用构造函数)
参考书籍:
1. C++ primer, Lippman
2. STL 源码分析, 侯捷
// Last Update:2014-04-11 15:44:44 /** * @file vector.h * @brief a simple vector class * @author [email protected] * @version 0.1.00 * @date 2014-04-09 */ #ifndef MY_VECTOR_H #define MY_VECTOR_H #include <iostream> #include <algorithm> #include <memory> template<class T> void destroy(T* pointer) { pointer->~T(); } template<class ForwardIterator> void destroy(ForwardIterator first, ForwardIterator last) { for(ForwardIterator it = first; it != last; ++ it) { destroy(&*it); } } template<class T> class MyVector { public: typedef T value_type; typedef T* iterator; typedef const T*const_iterator; typedef T* pointer; typedef const T* const_pointer; typedef T& reference; typedef const T& const_reference; typedef size_t size_type; MyVector(); MyVector(size_type n, T value = T()); MyVector(iterator begin, iterator end); ~MyVector(); //copy control MyVector(const MyVector&); MyVector& operator=(const MyVector&); bool empty() const { return begin() == end(); } size_type size() const {return (size_type)(finish - start);} size_type capacity() const {return (size_type)(end_of_storage - start);} iterator begin() { return start; } const_iterator begin() const{ return start; } iterator end() { return finish;} const_iterator end() const{ return finish; } reference operator[](size_type i){return *(start + i);} const_reference operator[](size_type i)const {return *(start + i);} void insert(iterator position, size_type n, const T& value); void push_back(const T& value); void pop_back(); void erase(iterator first, iterator last); void clear(); void reserve(size_type n); protected: iterator start; //空间的头 iterator finish; //空间的尾 iterator end_of_storage; //可用空间的尾巴 private: static std::allocator<T> alloc; // object to get raw memory }; // static class member needed to be defined outside of class template<class T> std::allocator<T> MyVector<T>::alloc; // default constructor template<class T> MyVector<T>::MyVector() : start(NULL), finish(NULL), end_of_storage(NULL) { } template<class T> MyVector<T>::MyVector(size_type n, T value) { start = alloc.allocate(n); end_of_storage = finish = start + n; for(iterator i=start; i!=finish; ++i) alloc.construct(i, value); } template<class T> MyVector<T>::MyVector(iterator begin, iterator end) { const size_type n = end - begin; /* allocate space */ start = alloc.allocate(n); finish = end_of_storage = start + n; /* call constructor */ std::uninitialized_copy(begin, end, start); } template<class T> MyVector<T>::~MyVector() { /* call destructor */ ::destroy(start, finish); /* free space */ alloc.deallocate(start, end_of_storage - start); } // copy control template<class T> MyVector<T>::MyVector(const MyVector& rhs) { start = alloc.allocate(rhs.capacity()); std::uninitialized_copy(rhs.start, rhs.finish, start); finish = start + (rhs.finish - rhs.start); end_of_storage = start + (rhs.end_of_storage - rhs.start); } template<class T> MyVector<T>& MyVector<T>::operator=(const MyVector& rhs) { start = alloc.allocate(rhs.capacity()); std::uninitialized_copy(rhs.start, rhs.finish, start); finish = start + rhs.finish - rhs.start; end_of_storage = start + rhs.end_of_storage - rhs.start; return *this; } template<class T> void MyVector<T>::insert(iterator position, size_type n, const T& value) { if(n <= end_of_storage - finish) {/* enough memory */ if(n <= finish - position) { std::uninitialized_copy(finish-n, finish, finish); std::copy(position, finish-n, position+n); std::fill_n(position, n, value); } else { std::uninitialized_fill_n(finish, n - (finish - position), value); std::uninitialized_copy(position, finish, position + n); std::fill(position, finish, value); } finish += n; } else {/* reallocate */ pointer new_start(NULL), new_finish(NULL); size_type old_type = end_of_storage - start; size_type new_size = old_type + std::max(old_type, n); new_start = alloc.allocate(new_size); // copy old vector to new vector new_finish = std::uninitialized_copy(start, position, new_start); std::uninitialized_fill_n(new_finish, n, value); new_finish += n; new_finish = std::uninitialized_copy(position, finish, new_finish); alloc.deallocate(start, end_of_storage - start); start = new_start; finish = new_finish; end_of_storage = new_start + new_size; } } template<class T> void MyVector<T>::push_back(const T &value) { insert(end(), 1, value); } template<class T> void MyVector<T>::pop_back() { alloc.destroy(--finish); } template<class T> void MyVector<T>::erase(iterator first, iterator last) { iterator old_finish = finish; finish = std::copy(last, finish, first); ::destroy(finish, old_finish); } template<class T> void MyVector<T>::clear() { erase(start, finish); } template<class T> void MyVector<T>::reserve(size_type n) { if(capacity() < n) { iterator new_start = alloc.allocate(n); std::uninitialized_copy(start, finish, new_start); ::destroy(start, finish); alloc.deallocate(start, size()); const size_type old_size = finish - start; start = new_start; finish = new_start + old_size; end_of_storage = new_start + n; } } #endif /*MY_VECTOR_H*/