之前用数组简单实现了vector,看了primer之后,用allocator类再次简单实现了vector,和数组相比较,allocator类分配内存和构造对象更容易。。
具体的代码:(有问题请指出)
1 Vector.h类:
#ifndef VECTOR_H #define VECTOR_H #include <memory> //allocator类 #include<iostream> #include<initializer_list> using namespace std; template <typename T> class Vector { public: typedef T* iterator; typedef const T* const_iterator; Vector() : elements(nullptr), first_free(nullptr), cap(nullptr) {} Vector(std::initializer_list<T> l); Vector(int initsize, T value); Vector(iterator b, iterator e); Vector(const Vector&); //拷贝构造函数 Vector& operator=(const Vector&); //拷贝赋值运算符 ~Vector();//析构函数 //新标准 Vector(Vector&&);//移动构造函数 Vector& operator=(Vector&&);//移动赋值运算符 bool empty()const { return first_free == elements; } size_t size() const { return first_free - elements; } size_t capacity() const { return cap - elements; } iterator begin() const{ return elements; } iterator end() const { return first_free; } const_iterator cbegin() const { return elements; } const_iterator cend() const { return first_free; } bool operator==(const Vector<T>& rhs); bool operator!=(const Vector<T>& rhs); void reserve(size_t new_cap); void resize(size_t count); void resize(size_t count, const T& s); T &operator[](int index); const T &operator[](int index) const; T &front(); const T &front() const; T &back(); const T &back() const; void push_back(const T&); iterator insert(iterator b, const T& value); void pop_back() { first_free--; alloc.destroy(first_free); } iterator erase(iterator b); void clear(); private: std::pair<T*, T*> alloc_n_copy(const T*, const T*); //分配内存,拷贝一定范围中的元素 void free(); //析构对象和释放内存 void chk_n_alloc() { if (size() == capacity()) reallocate(); } void reallocate(); void alloc_n_move(size_t new_cap); private: T *elements; T *first_free; //指向尾后元素 T *cap; //指向内存末尾之后的位置 static std::allocator<T> alloc; }; template <typename T> std::allocator<T> Vector<T>::alloc; template<typename T> Vector<T>::Vector(std::initializer_list<T> l) //列表初始化 { T* const newData = alloc.allocate(l.size()); //常量指针 T* p = newData; for (const auto &t : l) alloc.construct(p++, t); elements = newData; first_free = cap = elements + l.size(); } template<typename T> Vector<T>::Vector(int initsize, T value) { T* const data = alloc.allocate(initsize); T* p = data; //uninitialized_fill_n(p, initsize, value) //可以用下面的for语句代替 for (int i = 0; i != initsize; ++i) alloc.construct(p++, value); elements = data; first_free = cap = elements + initsize; } template<typename T> Vector<T>::Vector(iterator b, iterator e) { int num = e - b; T* const data = alloc.allocate(num); T* p = data; //uninitialized_copy(b, e, p); //这里传p是因为怕要求data指针发生变化,可以用for语句代替,作用是一样的 for (; b != e; ++b) alloc.construct(p++, *b); elements = data; first_free = cap = elements + num; } template <typename T> std::pair<T*, T*> Vector<T>::alloc_n_copy(const T* b, const T* e) { auto data = alloc.allocate(e - b); auto olddata=data; for (; b != e; ++b) alloc.construct(data++, *b); //return make_pair( data, std::uninitialized_copy(b, e, data)) ; //新标准,返回的是新分配的内存中范围迭代器 return make_pair(olddata, data); } template <typename T> void Vector<T>::free() { if (elements) { for (auto p = first_free; p != elements;) alloc.destroy(--p); //析构对象 alloc.deallocate(elements, cap - elements); //释放内存 } } template <typename T> Vector<T>::Vector(const Vector &rhs) //拷贝构造函数 { auto newdata = alloc_n_copy(rhs.begin(), rhs.end()); elements = newdata.first; first_free = cap = newdata.second; } template <typename T> Vector<T>::~Vector() { free(); } template <typename T> Vector<T>& Vector<T>::operator=(const Vector &rhs) { auto data = alloc_n_copy(rhs.begin(), rhs.end()); free(); elements = data.first; first_free = cap = data.second; return *this; } //移动构造函数 template <typename T> Vector<T>::Vector(Vector &&s) :elements(s.elements), first_free(s.first_free), cap(s.cap) { s.elements = s.first_free = s.cap = nullptr; } //移动赋值运算符 template <typename T> Vector<T>& Vector<T>::operator = (Vector &&rhs) { if (this != &rhs) { free(); elements = rhs.elements; first_free = rhs.first_free; cap = rhs.cap; rhs.elements = rhs.first_free = rhs.cap = nullptr; } return *this; } template<typename T> bool Vector<T>::operator==(const Vector<T>& rhs) { if (first_free - elements == rhs.first_free - rhs.elements) { int cnt = 0; for (T *p = elements, *q = rhs.elements; p != first_free&& q != rhs.first_free; ++p, ++q) if (*p ==*q) ++cnt; if (cnt == first_free - elements) return true; } return false; } template<typename T> bool Vector<T>::operator!=(const Vector<T>& rhs) { return !(*this == rhs); } //分配new_cap个的内存空间。 template <typename T> void Vector<T>::alloc_n_move(size_t new_cap) { auto newdata = alloc.allocate(new_cap); auto dest = newdata; T* elem = elements; for (size_t i = 0; i != this->size(); ++i) alloc.construct(dest++, std::move(*elem++)); free(); elements = newdata; first_free = dest; cap = elements + new_cap; } template <typename T> void Vector<T>::reallocate() { auto newcapacity = size() ? 2 * size() : 1; alloc_n_move(newcapacity); } template <typename T> void Vector<T>::reserve(size_t new_cap) { if (new_cap <= capacity()) return; alloc_n_move(new_cap); } template <typename T> void Vector<T>::resize(size_t count, const T &s) { if (count > size()) { if (count > capacity()) reserve(count * 2); for (size_t i = size(); i != count; ++i) alloc.construct(first_free++, s); } else if (count < size()) { while (first_free != elements + count) alloc.destroy(--first_free); //析构对象 } } template <typename T> void Vector<T>::resize(size_t count) { resize(count, T()); } template<typename T> T &Vector<T>::operator[](int index) { if (index < 0 || index >= size()) { cout << "out of memory" << endl; exit(0); } return elements[index]; } template<typename T> const T &Vector<T>::operator[] (int index) const { if (index < 0 || index >= size()) { cout << "out of memory" << endl; exit(0); } return elements[index]; } template<typename T> T& Vector<T>::front() { if (!this->empty()) return elements[0]; } template<typename T> const T& Vector<T>::front() const { if (!this->empty()) return elements[0]; } template<typename T> T& Vector<T>::back() { if (!this->empty()) return elements[size() - 1]; } template<typename T> const T& Vector<T>::back() const { if (!this->empty()) return elements[size() - 1]; } template <typename T> void Vector<T>::push_back(const T &s) { chk_n_alloc(); alloc.construct(first_free++, s); } template<typename T> T* Vector<T>::insert(iterator b, const T &value) { if (b < elements || b> first_free) //b可以为尾后迭代器 { cout << "out of memory" << endl; exit(0); } int num = b - elements; if (size() == capacity()) { reallocate(); b = elements + num; //重新分配内存后原来的指针b失效了,所以此处令b指向新分配的内存中 } for (iterator p = first_free; p > b; p--) *p = *(p - 1); *b = value; first_free++; return b; } template<typename T> T* Vector<T>::erase(iterator b) { if (b < elements || b >= first_free) //确保迭代器在范围内,否则未定义,b不能为尾后迭代器 { cout << "out of memory" << endl; exit(0); } iterator q = b + 1; int num = q - elements; iterator p = first_free - 1; for (; b < p; b++) *b = *(b + 1); first_free--; if (size() <= capacity() / 4) //防止删除后空闲空间太大,浪费空间 { reallocate(); iterator q1 = elements + num; //重新进行内存分配后原来的指针q可能失效了 return q1; } return q; } template<typename T> void Vector<T>::clear() { while(elements != first_free) alloc.destroy(--first_free); } #endif
2 测试代码(和之前一样)
#include <string> #include"Vector.h" //注意当这里不是标准库的头文件,是自己写的,要用双引号,整了好久,还以为程序出错了。。 using namespace std; int main() { // 利用构造函数 Vector<int> v1; Vector<int> v2(5, 9); Vector<int> v3(v2); Vector<int> v4(v2.begin(), v2.end()); if (v1.empty()) cout << "v1为空,大小为:" << v1.size() << endl; cout << "向v1插入元素:"; int a; while (cin >> a) v1.push_back(a); if (!v1.empty()) cout << "v1不为空,大小为:" << v1.size() << "容量为:" << v1.capacity() << endl; cout << "元素为:"; for (Vector<int>::iterator iter = v1.begin(); iter != v1.end(); ++iter) cout << *iter << " "; cout << endl; cout << "重新插入后:"; v1.insert(v1.begin() + 1, 4); cout << "此时v1大小为:" << v1.size() << "容量为:" << v1.capacity() << endl; cout << "元素为:"; for (Vector<int>::iterator iter = v1.begin(); iter != v1.end(); ++iter) cout << *iter << " "; cout << endl; cout << "删除元素后为:"; v1.pop_back(); for (Vector<int>::iterator iter = v1.begin(); iter != v1.end(); ++iter) cout << *iter << " "; cout << endl; cout << "再次删除元素后为:"; v1.erase(v1.begin() + 2); for (Vector<int>::iterator iter = v1.begin(); iter != v1.end(); ++iter) cout << *iter << " "; cout << endl; cout << "v2元素为:"; for (Vector<int>::iterator iter = v2.begin(); iter != v2.end(); ++iter) cout << *iter << " "; cout << endl; cout << "v3元素为:"; for (Vector<int>::iterator iter = v3.begin(); iter != v3.end(); ++iter) cout << *iter << " "; cout << endl; cout << "v4元素为:"; for (Vector<int>::iterator iter = v4.begin(); iter != v4.end(); ++iter) cout << *iter << " "; cout << endl; if (v1 == v3) cout << "v1与v3相等"; else cout << "v1与v3不相等" << endl; Vector<int> v = { 1, 2, 3, 4, 5 }; Vector<int> v5; v5 = v; cout << "v5元素为:"; for (Vector<int>::iterator iter = v5.begin(); iter != v5.end(); ++iter) cout << *iter << " "; cout << endl; v5.push_back(99); v5.resize(2, 2); cout << "操作后v5元素为:"; for (Vector<int>::iterator iter = v5.begin(); iter != v5.end(); ++iter) cout << *iter << " "; cout << endl; std::cout << v5.capacity() << "\n"; return 0; }
3 运行结果: