实现一个简单的vector – turbo_vector
本篇不提供allocator部分
我们需要实现一个模板类,并且提供以下方法和成员
template <typename T> class turbo_vector { public: turbo_vector(); ~turbo_vector(); void push_back(const T & value); void pop_back(); int size() const; int capacity() const; void reserve(int size); void resize(int size); T & at(int index); T & front(); T & back(); bool empty() const; void clear(); T & operator [] (int index); turbo_vector<T> & operator = (const turbo_vector<T> & other); T * data(); void swap(turbo_vector<T> & other); protected: T * data_; // 记录数组数据 int size_; // 记录数组大小 int capacity_; // 容量,记录数组容量 };
重要函数
push_back
template<typename T> void turbo_vector<T>::push_back(const T &value) { // 首先我们需要知道当前大小是否超过数组已有空间 if (size_ < capacity_) { data_[size_] = value; size_++; return; } // 如果超过则扩大数组空间,如果不超过则直接插入数据 if (capacity_ == 0) { capacity_ = 1; } else { capacity_ *= 2; } T * data = new T[capacity_]; if (is_basic_type()) { // 基本类型使用copy速度显著提升 std::memcpy(data, data_, size_ * sizeof(T)); } else { // 拷贝原有数据 for (int i = 0; i < size_; i++) { data[i] = data_[i]; } } // 释放原有空间 if (data_ != nullptr) { delete [] data_; data_ = nullptr; } // 插入新数据 data_ = data; data_[size_] = value; size_++; }
reserve
template<typename T> void turbo_vector<T>::reserve(int size) { // 如果现有空间比size大则不做操作 ,标准库也是这么做的 if (capacity_ >= size) { return; } while (capacity_ < size) { if (capacity_ == 0) { capacity_ = 1; } else { capacity_ *= 2; } } T * data = new T[capacity_]; if (is_basic_type()) { std::memcpy(data, data_, size_ * sizeof(T)); } else { // 拷贝原有数据 for (int i = 0; i < size_; i++) { data[i] = data_[i]; } } // 释放原有空间并且将使用新空间 if (data_ != nullptr) { delete [] data_; data_ = nullptr; } data_ = data; }
resize
template<typename T> void turbo_vector<T>::resize(int size) { // size_大则重置 if (size_ >= size) { size_ = size; return; } // 如果size大且比空间小,则初始化多余部分 if (size <= capacity_) { for (int i = size_; i < size; i++) { data_[i] = T(); } size_ = size; return; } // 否则扩张初始化新的部分 while (capacity_ < size) { if (capacity_ == 0) { capacity_ = 1; } else { capacity_ *= 2; } } T * data = new T[capacity_]; if (is_basic_type()) { std::memcpy(data, data_, size_ * sizeof(T)); } else { for (int i = 0; i < size_; i++) { data[i] = data_[i]; } } for (int i = size_; i < size; i++) { data[i] = T(); } if (data_ != nullptr) { delete [] data_; data_ = nullptr; } data_ = data; size_ = size; }
at
template<typename T> T &turbo_vector<T>::at(int index) { // at有异常部分 if (index < 0 || index >= size_) { throw std::logic_error("out of range"); } return data_[index]; }
operator=
template<typename T> turbo_vector<T> &turbo_vector<T>::operator=(const turbo_vector<T> &other) { // 如果capacity() 比新的小则直接全部重建 if (capacity_ < other.m_size) { if (data_ != nullptr) { delete [] data_; data_ = nullptr; size_ = 0; capacity_ = 0; } while (capacity_ < other.m_size) { if (capacity_ == 0) { capacity_ = 1; } else { capacity_ *= 2; } } data_ = new T[capacity_]; } if (is_basic_type()) { std::memcpy(data_, other.m_data, size_ * sizeof(T)); } else { for (int i = 0; i < other.m_size; i++) { data_[i] = other.m_data[i]; } } size_ = other.m_size; return *this; }
swap
template<typename T> void turbo_vector<T>::swap(turbo_vector<T> &other) { // 传统拷贝 T * data = other.m_data; int size = other.m_size; int capacity = other.m_capacity; other.m_data = data_; other.m_size = size_; other.m_capacity = capacity_; data_ = data; size_ = size; capacity_ = capacity; }
至此基本函数就已经提供完成
迭代器
之后我们还需要提供一个正向的迭代器和一个逆向的迭代器
并且提供迭代器相关的函数
class iterator { public: iterator() : pointer_(nullptr) {} iterator(T * pointer) : pointer_(pointer) {} ~iterator() {} bool operator == (const iterator & other); bool operator != (const iterator & other); iterator & operator = (const iterator & other); iterator & operator ++ (); iterator operator ++ (int); iterator operator + (int i); iterator & operator += (int i); iterator operator - (int i); iterator & operator -= (int i); int operator - (const iterator & other) const; T & operator * (); T * operator -> (); private: T * pointer_; }; class reverse_iterator { public: reverse_iterator() : pointer_(nullptr) {} reverse_iterator(T * pointer) : pointer_(pointer) {} ~reverse_iterator() {} bool operator == (const reverse_iterator & other); bool operator != (const reverse_iterator & other); reverse_iterator & operator = (const reverse_iterator & other); reverse_iterator & operator ++ (); reverse_iterator operator ++ (int); reverse_iterator operator + (int i); reverse_iterator & operator += (int i); reverse_iterator operator - (int i); reverse_iterator & operator -= (int i); T & operator * (); T * operator -> (); private: T * pointer_; }; reverse_iterator rbegin(); reverse_iterator rend(); iterator begin(); iterator end(); iterator find(const T & value); iterator rfind(const T & value); iterator insert(iterator pos, const T & value); iterator insert(iterator pos, int n, const T & value); iterator erase(iterator pos); iterator erase(iterator first, iterator last); template<typename T> typename turbo_vector<T>::reverse_iterator turbo_vector<T>::rbegin() { turbo_vector<T>::reverse_iterator it(data_ + size_ - 1); return it; } template<typename T> typename turbo_vector<T>::reverse_iterator turbo_vector<T>::rend() { turbo_vector<T>::reverse_iterator it(data_ - 1); return it; } template<typename T> typename turbo_vector<T>::iterator turbo_vector<T>::begin() { turbo_vector<T>::iterator it(data_); return it; } template<typename T> typename turbo_vector<T>::iterator turbo_vector<T>::end() { turbo_vector<T>::iterator it(data_ + size_); return it; } template<typename T> typename turbo_vector<T>::iterator turbo_vector<T>::find(const T &value) { for (turbo_vector<T>::iterator it = begin(); it != end(); it++) { if (*it == value) { return it; } } return end(); } template<typename T> typename turbo_vector<T>::iterator turbo_vector<T>::rfind(const T &value) { for (turbo_vector<T>::reverse_iterator it = rbegin(); it != rend(); it++) { if (*it == value) { return turbo_vector<T>::iterator(it.operator->()); } } return end(); } template<typename T> typename turbo_vector<T>::iterator turbo_vector<T>::insert(turbo_vector::iterator pos, const T &value) { return insert(pos, 1, value); } template<typename T> typename turbo_vector<T>::iterator turbo_vector<T>::insert(turbo_vector::iterator pos, int n, const T &value) { int size = pos - begin(); if (size_ + n <= capacity_) { if (is_basic_type()) { std::memmove(data_ + size + n, data_ + size, (size_ - size) * sizeof(T)); } else { for (int i = size_; i > size; i--) { data_[i + n - 1] = data_[i - 1]; } } for (int i = 0; i < n; i++) { data_[size + i] = value; } size_ += n; return turbo_vector<T>::iterator(data_ + size); } while (size_ + n > capacity_) { if (capacity_ == 0) { capacity_ = 1; } else { capacity_ *= 2; } } T * data = new T[capacity_]; if (is_basic_type()) { std::memcpy(data, data_, size * sizeof(T)); } else { for (int i = 0; i < size; i++) { data[i] = data_[i]; } } for (int i = 0; i < n; i++) { data[size + i] = value; } if (is_basic_type()) { std::memcpy(data + size + n, data_ + size, (size_ - size) * sizeof(T)); } else { for (int i = size; i < size_; i++) { data[i + n] = data_[i]; } } if (data_ != nullptr) { delete [] data_; data_ = nullptr; } data_ = data; size_ += n; return turbo_vector<T>::iterator(data_ + size); } template<typename T> typename turbo_vector<T>::iterator turbo_vector<T>::erase(turbo_vector::iterator pos) { if (end() - pos == 1) { size_ -= 1; return end(); } int size = pos - begin(); if (is_basic_type()) { std::memmove(data_ + size, data_ + size + 1, (size_ - size - 1) * sizeof(T)); } else { for (int i = size; i < size_ - 1; i++) { data_[i] = data_[i + 1]; } } size_ -= 1; return pos; } template<typename T> typename turbo_vector<T>::iterator turbo_vector<T>::erase(turbo_vector::iterator first, turbo_vector::iterator last) { int f = first - begin(); int l = last - begin(); int n = last - first; if (is_basic_type()) { std::memmove(data_ + f, data_ + l, (size_ - l) * sizeof(T)); } else { for (int i = 0; i < size_ - l; i++) { data_[f] = data_[l]; } } size_ -= n; return first; }
全部代码
turbo_vector.h
#ifndef ALGOTEST_TURBO_VECTOR_H #define ALGOTEST_TURBO_VECTOR_H #include <type_traits> #include <typeinfo> #include <cstring> #include <stdexcept> namespace turbo { template <typename T> class turbo_vector { public: turbo_vector(); ~turbo_vector(); void push_back(const T & value); void pop_back(); int size() const; int capacity() const; void reserve(int size); void resize(int size); T & at(int index); T & front(); T & back(); bool empty() const; void clear(); T & operator [] (int index); turbo_vector<T> & operator = (const turbo_vector<T> & other); T * data(); void swap(turbo_vector<T> & other); class iterator { public: iterator() : pointer_(nullptr) {} iterator(T * pointer) : pointer_(pointer) {} ~iterator() {} bool operator == (const iterator & other); bool operator != (const iterator & other); iterator & operator = (const iterator & other); iterator & operator ++ (); iterator operator ++ (int); iterator operator + (int i); iterator & operator += (int i); iterator operator - (int i); iterator & operator -= (int i); int operator - (const iterator & other) const; T & operator * (); T * operator -> (); private: T * pointer_; }; class reverse_iterator { public: reverse_iterator() : pointer_(nullptr) {} reverse_iterator(T * pointer) : pointer_(pointer) {} ~reverse_iterator() {} bool operator == (const reverse_iterator & other); bool operator != (const reverse_iterator & other); reverse_iterator & operator = (const reverse_iterator & other); reverse_iterator & operator ++ (); reverse_iterator operator ++ (int); reverse_iterator operator + (int i); reverse_iterator & operator += (int i); reverse_iterator operator - (int i); reverse_iterator & operator -= (int i); T & operator * (); T * operator -> (); private: T * pointer_; }; reverse_iterator rbegin(); reverse_iterator rend(); iterator begin(); iterator end(); iterator find(const T & value); iterator rfind(const T & value); iterator insert(iterator pos, const T & value); iterator insert(iterator pos, int n, const T & value); iterator erase(iterator pos); iterator erase(iterator first, iterator last); protected: bool is_basic_type(); private: T * data_{nullptr}; // 记录数组数据 int size_{0}; // 记录数组大小 int capacity_{0}; // 容量,记录数组容量 }; template<typename T> turbo_vector<T>::turbo_vector() { } template<typename T> turbo_vector<T>::~turbo_vector() { if (data_ != nullptr) { delete [] data_; data_ = nullptr; } size_ = 0; capacity_ = 0; } template<typename T> void turbo_vector<T>::push_back(const T &value) { // 首先我们需要知道当前大小是否超过数组已有空间 if (size_ < capacity_) { data_[size_] = value; size_++; return; } // 如果超过则扩大数组空间,如果不超过则直接插入数据 if (capacity_ == 0) { capacity_ = 1; } else { capacity_ *= 2; } T * data = new T[capacity_]; if (is_basic_type()) { // 基本类型使用copy速度显著提升 std::memcpy(data, data_, size_ * sizeof(T)); } else { // 拷贝原有数据 for (int i = 0; i < size_; i++) { data[i] = data_[i]; } } // 释放原有空间 if (data_ != nullptr) { delete [] data_; data_ = nullptr; } // 插入新数据 data_ = data; data_[size_] = value; size_++; } template<typename T> void turbo_vector<T>::pop_back() { // 直接数据数量操作,不对数组进行操作 if (size_ > 0) { size_--; } } template<typename T> int turbo_vector<T>::size() const { return size_; } template<typename T> int turbo_vector<T>::capacity() const { return capacity_; } template<typename T> void turbo_vector<T>::reserve(int size) { // 如果现有空间比size大则不做操作 ,标准库也是这么做的 if (capacity_ >= size) { return; } while (capacity_ < size) { if (capacity_ == 0) { capacity_ = 1; } else { capacity_ *= 2; } } T * data = new T[capacity_]; if (is_basic_type()) { std::memcpy(data, data_, size_ * sizeof(T)); } else { // 拷贝原有数据 for (int i = 0; i < size_; i++) { data[i] = data_[i]; } } // 释放原有空间并且将使用新空间 if (data_ != nullptr) { delete [] data_; data_ = nullptr; } data_ = data; } template<typename T> void turbo_vector<T>::resize(int size) { // size_大则重置 if (size_ >= size) { size_ = size; return; } // 如果size大且比空间小,则初始化多余部分 if (size <= capacity_) { for (int i = size_; i < size; i++) { data_[i] = T(); } size_ = size; return; } // 否则扩张初始化新的部分 while (capacity_ < size) { if (capacity_ == 0) { capacity_ = 1; } else { capacity_ *= 2; } } T * data = new T[capacity_]; if (is_basic_type()) { std::memcpy(data, data_, size_ * sizeof(T)); } else { for (int i = 0; i < size_; i++) { data[i] = data_[i]; } } for (int i = size_; i < size; i++) { data[i] = T(); } if (data_ != nullptr) { delete [] data_; data_ = nullptr; } data_ = data; size_ = size; } template<typename T> T &turbo_vector<T>::at(int index) { // at有异常部分 if (index < 0 || index >= size_) { throw std::logic_error("out of range"); } return data_[index]; } template<typename T> T &turbo_vector<T>::front() { if (size_ <= 0) { throw std::logic_error("vector is empty"); } return data_[0]; } template<typename T> T &turbo_vector<T>::back() { if (size_ <= 0) { throw std::logic_error("vector is empty"); } return data_[size_ - 1]; } template<typename T> bool turbo_vector<T>::empty() const { return size_ == 0; } template<typename T> void turbo_vector<T>::clear() { size_ = 0; } template<typename T> T &turbo_vector<T>::operator[](int index) { return at(index); } template<typename T> turbo_vector<T> &turbo_vector<T>::operator=(const turbo_vector<T> &other) { // 如果capacity() 比新的小则直接全部重建 if (capacity_ < other.m_size) { if (data_ != nullptr) { delete [] data_; data_ = nullptr; size_ = 0; capacity_ = 0; } while (capacity_ < other.m_size) { if (capacity_ == 0) { capacity_ = 1; } else { capacity_ *= 2; } } data_ = new T[capacity_]; } if (is_basic_type()) { std::memcpy(data_, other.m_data, size_ * sizeof(T)); } else { for (int i = 0; i < other.m_size; i++) { data_[i] = other.m_data[i]; } } size_ = other.m_size; return *this; } template<typename T> T *turbo_vector<T>::data() { return data_; } template<typename T> void turbo_vector<T>::swap(turbo_vector<T> &other) { // 传统拷贝 T * data = other.m_data; int size = other.m_size; int capacity = other.m_capacity; other.m_data = data_; other.m_size = size_; other.m_capacity = capacity_; data_ = data; size_ = size; capacity_ = capacity; } template<typename T> bool turbo_vector<T>::is_basic_type() { if (std::is_pointer<T>::value) { return true; } return (typeid(T) == typeid(bool)) || (typeid(T) == typeid(char)) || (typeid(T) == typeid(unsigned char)) || (typeid(T) == typeid(short)) || (typeid(T) == typeid(unsigned short)) || (typeid(T) == typeid(int)) || (typeid(T) == typeid(unsigned int)) || (typeid(T) == typeid(long)) || (typeid(T) == typeid(unsigned long)) || (typeid(T) == typeid(float)) || (typeid(T) == typeid(double)); } template<typename T> typename turbo_vector<T>::reverse_iterator turbo_vector<T>::rbegin() { turbo_vector<T>::reverse_iterator it(data_ + size_ - 1); return it; } template<typename T> typename turbo_vector<T>::reverse_iterator turbo_vector<T>::rend() { turbo_vector<T>::reverse_iterator it(data_ - 1); return it; } template<typename T> typename turbo_vector<T>::iterator turbo_vector<T>::begin() { turbo_vector<T>::iterator it(data_); return it; } template<typename T> typename turbo_vector<T>::iterator turbo_vector<T>::end() { turbo_vector<T>::iterator it(data_ + size_); return it; } template<typename T> typename turbo_vector<T>::iterator turbo_vector<T>::find(const T &value) { for (turbo_vector<T>::iterator it = begin(); it != end(); it++) { if (*it == value) { return it; } } return end(); } template<typename T> typename turbo_vector<T>::iterator turbo_vector<T>::rfind(const T &value) { for (turbo_vector<T>::reverse_iterator it = rbegin(); it != rend(); it++) { if (*it == value) { return turbo_vector<T>::iterator(it.operator->()); } } return end(); } template<typename T> typename turbo_vector<T>::iterator turbo_vector<T>::insert(turbo_vector::iterator pos, const T &value) { return insert(pos, 1, value); } template<typename T> typename turbo_vector<T>::iterator turbo_vector<T>::insert(turbo_vector::iterator pos, int n, const T &value) { int size = pos - begin(); if (size_ + n <= capacity_) { if (is_basic_type()) { std::memmove(data_ + size + n, data_ + size, (size_ - size) * sizeof(T)); } else { for (int i = size_; i > size; i--) { data_[i + n - 1] = data_[i - 1]; } } for (int i = 0; i < n; i++) { data_[size + i] = value; } size_ += n; return turbo_vector<T>::iterator(data_ + size); } while (size_ + n > capacity_) { if (capacity_ == 0) { capacity_ = 1; } else { capacity_ *= 2; } } T * data = new T[capacity_]; if (is_basic_type()) { std::memcpy(data, data_, size * sizeof(T)); } else { for (int i = 0; i < size; i++) { data[i] = data_[i]; } } for (int i = 0; i < n; i++) { data[size + i] = value; } if (is_basic_type()) { std::memcpy(data + size + n, data_ + size, (size_ - size) * sizeof(T)); } else { for (int i = size; i < size_; i++) { data[i + n] = data_[i]; } } if (data_ != nullptr) { delete [] data_; data_ = nullptr; } data_ = data; size_ += n; return turbo_vector<T>::iterator(data_ + size); } template<typename T> typename turbo_vector<T>::iterator turbo_vector<T>::erase(turbo_vector::iterator pos) { if (end() - pos == 1) { size_ -= 1; return end(); } int size = pos - begin(); if (is_basic_type()) { std::memmove(data_ + size, data_ + size + 1, (size_ - size - 1) * sizeof(T)); } else { for (int i = size; i < size_ - 1; i++) { data_[i] = data_[i + 1]; } } size_ -= 1; return pos; } template<typename T> typename turbo_vector<T>::iterator turbo_vector<T>::erase(turbo_vector::iterator first, turbo_vector::iterator last) { int f = first - begin(); int l = last - begin(); int n = last - first; if (is_basic_type()) { std::memmove(data_ + f, data_ + l, (size_ - l) * sizeof(T)); } else { for (int i = 0; i < size_ - l; i++) { data_[f] = data_[l]; } } size_ -= n; return first; } template<typename T> bool turbo_vector<T>::iterator::operator==(const turbo_vector::iterator &other) { return pointer_ == other.pointer_; } template<typename T> bool turbo_vector<T>::iterator::operator!=(const turbo_vector::iterator &other) { return pointer_ != other.pointer_; } template<typename T> typename turbo_vector<T>::iterator &turbo_vector<T>::iterator::operator=(const turbo_vector::iterator &other) { pointer_ = other.pointer_; return *this; } template<typename T> typename turbo_vector<T>::iterator &turbo_vector<T>::iterator::operator++() { pointer_ += 1; return *this; } template<typename T> typename turbo_vector<T>::iterator turbo_vector<T>::iterator::operator++(int) { iterator it = *this; ++(*this); return it; } template<typename T> typename turbo_vector<T>::iterator turbo_vector<T>::iterator::operator+(int i) { iterator it = *this; it.pointer_ += i; return it; } template<typename T> typename turbo_vector<T>::iterator &turbo_vector<T>::iterator::operator+=(int i) { pointer_ += i; return *this; } template<typename T> typename turbo_vector<T>::iterator turbo_vector<T>::iterator::operator-(int i) { iterator it = *this; it.pointer_ -= i; return it; } template<typename T> typename turbo_vector<T>::iterator &turbo_vector<T>::iterator::operator-=(int i) { pointer_ -= i; return *this; } template<typename T> int turbo_vector<T>::iterator::operator-(const turbo_vector::iterator &other) const { return pointer_ - other.pointer_; } template<typename T> T &turbo_vector<T>::iterator::operator*() { return *pointer_; } template<typename T> T *turbo_vector<T>::iterator::operator->() { return pointer_; } template<typename T> bool turbo_vector<T>::reverse_iterator::operator==(const turbo_vector::reverse_iterator &other) { return pointer_ == other.pointer_; } template<typename T> bool turbo_vector<T>::reverse_iterator::operator!=(const turbo_vector::reverse_iterator &other) { return pointer_ != other.pointer_; } template<typename T> typename turbo_vector<T>::reverse_iterator & turbo_vector<T>::reverse_iterator::operator=(const turbo_vector::reverse_iterator &other) { pointer_ = other.pointer_; return *this; } template<typename T> typename turbo_vector<T>::reverse_iterator &turbo_vector<T>::reverse_iterator::operator++() { pointer_ -= 1; return *this; } template<typename T> typename turbo_vector<T>::reverse_iterator turbo_vector<T>::reverse_iterator::operator++(int) { reverse_iterator it = *this; ++(*this); return it; } template<typename T> typename turbo_vector<T>::reverse_iterator turbo_vector<T>::reverse_iterator::operator+(int i) { reverse_iterator it = *this; it.pointer_ -= i; return it; } template<typename T> typename turbo_vector<T>::reverse_iterator &turbo_vector<T>::reverse_iterator::operator+=(int i) { pointer_ -= i; return *this; } template<typename T> typename turbo_vector<T>::reverse_iterator turbo_vector<T>::reverse_iterator::operator-(int i) { reverse_iterator it = *this; it.pointer_ += i; return it; } template<typename T> typename turbo_vector<T>::reverse_iterator &turbo_vector<T>::reverse_iterator::operator-=(int i) { pointer_ += i; return *this; } template<typename T> T &turbo_vector<T>::reverse_iterator::operator*() { return *pointer_; } template<typename T> T *turbo_vector<T>::reverse_iterator::operator->() { return pointer_; } } #endif //ALGOTEST_TURBO_VECTOR_H