模拟实现vector只是实现了一些基础功能,复杂一些操作可能会存在bug。
一些相关知识点在注释标注
#pragma once
#include <assert.h>
namespace QBL
{
template <class T>
class vector
{
public:
typedef T* iterator;
typedef const T* const_iterator;
iterator begin()
{
return _start;
}
iterator end()
{
return _finish;
}
const_iterator begin()const
{
return _start;
}
const_iterator end()const
{
return _finish;
}
size_t size()const
{
return _finish - _start;//指针相减得到的是元素的个数
}
size_t capacity()const
{
return _endofstorage - _start;//指针相减得到的是元素的个数
}
vector()
{
}
//size_t i; unsigned __int64 size_t在vs64为下是unsigned __int64 而10u是unsigned int,那么对于编译器来说,
//不管是unsigned __int64 还是int都不是绝对符合匹配,那么都是模糊匹配,那么就出问题了,不清楚具体是匹配哪一个了
//而在vs32平台下 size_t 就是unsigned int,能够精确匹配到,所以就通过了
vector(size_t n, const T& v = T())//使用n个v进行构造
{
reserve(n);
for (size_t i = 0; i < n; i++)
{
push_back(v);
}
}
vector(int n, const T& v = T())//写一个上面的重载的版本,避免int类型去调用迭代器区间构造
{
reserve(n);
for (int i = 0; i < n; i++)
{
push_back(v);
}
}
vector(const vector<T>& v)
{
reserve(v.capacity());//省的扩容
for (auto& e : v)//当T为自定义类型的时候,e就会执行拷贝构造,所以使用引用会比较好
{
push_back(e);
}
}
template <class InputIterator>//之所以写为模板就是想实现不单单是*this类型的才能构造,通过隐式类型转换也可以构造
vector(InputIterator first, InputIterator last)//使用迭代器区间构造
{
while (first != last)
{
push_back(*first);
++first;
}
}
T& operator[](size_t pos)
{
assert(pos < size());
return *(_start + pos);
}
const T& operator[](size_t pos)const
{
assert(pos < size());
return *(_start + pos);
}
void swap(vector<T>& v)
{
std::swap(_start, v._start);
std::swap(_finish, v._finish);
std::swap(_endofstorage, v._endofstorage);
}
/*vector<T>& operator=(const vector<T>& v)
{
delete[] _start;
T* tmp = new T[v.capacity()];
size_t newsize = v.size();
memcpy(tmp, v._start, newsize * sizeof(T));
_start = tmp;
_finish = _start + newsize;
_endofstorage = _start + v.capacity();
return *this;
}*/
vector<T>& operator=(vector<T> v)
{
delete[] _start;
swap(v);
return *this;
}
void reserve(size_t n)//扩容
{
if (n > capacity())
{
size_t old_size = size();
T* tmp = new T[n];
//memcpy(tmp, _start, old_size * sizeof(T));//当套两层时只完成了一层的深拷贝
for (size_t i = 0; i < old_size; i++)
{
tmp[i] = _start[i];//此时如果是自定义类,调用的就是自定义类的赋值,就会完成自定义类的深拷贝
}
delete[] _start;
_start = tmp;
_finish = _start + old_size;
_endofstorage = _start + n;
}
}
void resize(size_t n, const T& v = T())//扩大时,使用匿名对象当缺省值更方便,因为元素类型不确定,此时匿名对象可以是自定义类型
{//C++中内置类型也有构造函数,所以上面的缺省值没有问题
if (n > size())
{
reserve(n);
while (_finish < _start + n)
{
*_finish = v;
++_finish;
}
}
else
{
_finish = _start + n;
}
}
void push_back(const T& v)
{
/*if (_finish == _endofstorage)
{
reserve(capacity() == 0 ? 4 : 2 * capacity());
}
*_finish = v;
++_finish;*/
insert(_finish, v);
}
void pop_back()
{
assert(size());
--_finish;
}
void insert(iterator pos, const T& v)//在pos位置插入,pos是一个迭代器
{
assert(pos <= _finish && pos >= _start);//等于_finish的时候就是尾插
if (_finish == _endofstorage)
{
size_t len = pos - _start;
reserve(capacity() == 0 ? 4 : 2 * capacity());
pos = _start + len;//因为使用的是迭代器,所以扩容以后,使用了新空间时pos会是一个野指针,此时迭代器失效
}
iterator it = end();
while (it > pos)
{
*it = *(it - 1);
--it;
}
*pos = v;
++_finish;
}
void erase(iterator pos)//在pos位置删除,pos是一个迭代器
{
assert(pos < _finish && pos >= _start);//不能等于_finish,_finish位置的无元素
iterator it = pos;
while (it < _finish)
{
*it = *(it + 1);
++it;
}
--_finish;
}
~vector()
{
delete[] _start;
_start = nullptr;
_finish = nullptr;
_endofstorage = nullptr;
}
private:
iterator _start = nullptr;
iterator _finish = nullptr;//指向尾元素的下一个
iterator _endofstorage = nullptr;//指向整个顺序表的结尾,也就是空间结尾的下一个
};
template<class T>
void Print_Vector(const vector<T>& v)
{
/*for (size_t i = 0; i < v.size(); i++)
{
cout << v[i] << " ";
}
cout << endl;*/
//vecotr<T>::const_iterator it = v.begin();
//如果写为模板类的迭代器,会报错,因为编译器不认识it的类型,编译的时候类模板还没有实例化
//静态成员变量的写法也是vecotr<T>::,此时编译器不认识const_iterator是什么
//auto it = v.begin();//auto刚好可以避免上述的问题
//如果不用auto就可以写为:
typename vector<T>::const_iterator it = v.begin();//必须写为typename不能写class
while (it != v.end())
{
cout << *it << " ";
++it;
}
cout << endl;
/*for (auto e : v)
{
cout << e << " ";
}
cout << endl;*/
}
void test1()
{
vector<int> v;
v.push_back(1);
v.push_back(2);
v.push_back(3);
v.push_back(4);
v.push_back(5);
v.push_back(2);
v.push_back(1);
Print_Vector(v);
//v.Print();
}
void test2()
{
vector<int> v;
v.push_back(1);
v.push_back(2);
v.push_back(3);
v.push_back(4);
v.push_back(5);
v.push_back(2);
v.push_back(1);
Print_Vector(v);
Print_Vector(v);
//v.Print();
}
void test3()
{
vector<int> v;
v.push_back(1);
v.push_back(2);
v.push_back(3);
v.push_back(4);
v.push_back(5);
v.push_back(2);
v.push_back(1);
Print_Vector(v);
v.insert(v.begin() + 3, 69);
Print_Vector(v);
v.insert(v.begin(), 00);
Print_Vector(v);
//v.insert(v.begin() + 9, 99);
Print_Vector(v);
//v.Print();
}
void test4()
{
vector<int> v1;
vector<double> v2;
v1.push_back(1);
v1.push_back(3);
v1.push_back(4);
v1.push_back(2);
v1.push_back(1);
Print_Vector(v1);
v1.insert(v1.begin() + 3, 69);
Print_Vector(v1);
v1.insert(v1.begin(), 00);
Print_Vector(v1);
v1.insert(v1.begin() + 4, 99);
Print_Vector(v1);
v2.push_back(1.1);
v2.push_back(3.3);
v2.push_back(4.3);
v2.push_back(2.2);
v2.push_back(1.1);
Print_Vector(v2);
v2.insert(v2.begin() + 3, 6.9);
Print_Vector(v2);
v2.insert(v2.begin(), 0.0);
Print_Vector(v2);
v2.insert(v2.begin() + 4, 9.9);
Print_Vector(v2);
//v.Print();
}
void test5()
{
vector<double> v2;
v2.push_back(1.1);
v2.push_back(3.3);
Print_Vector(v2);
v2.insert(v2.begin() + 2, 6.9);
Print_Vector(v2);
v2.insert(v2.begin(), 0.0);
Print_Vector(v2);
v2.insert(v2.begin() + 3, 9.9);
Print_Vector(v2);
v2.erase(v2.begin() + 2);
Print_Vector(v2);
}
void test6()
{
vector<double> v2;
v2.push_back(1.1);
v2.push_back(3.3);
Print_Vector(v2);
v2.resize(100,3);
Print_Vector(v2);
}
void test7()
{
vector<double> v2;
v2.push_back(1.1);
v2.push_back(3.3);
Print_Vector(v2);
v2.resize(100, 3);
Print_Vector(v2);
vector<double> v3;
v3 = v2;
cout << "------------------" << endl;
Print_Vector(v3);
}
void test8()
{
vector<double> v2;
v2.push_back(1.1);
v2.push_back(2.3);
v2.push_back(3.3);
v2.push_back(2.3);
v2.push_back(1.3);
Print_Vector(v2);
cout << "------------------" << endl;
vector<int> v3(v2.begin() + 1, v2.end() - 1);
Print_Vector(v3);
}
void test9()
{
vector<int> v1(10, 3);//测试vector(size_t n, const T& v = T())时会去调用迭代器区间构造,因为n个v的构造时uint和int,不如迭代器区间符合
vector<double> v2(10, 3.3);
vector<int> v3(10u, 3);//加u说明是uint
Print_Vector(v1);
Print_Vector(v2);
Print_Vector(v3);
}
void test10()//由此可以验证自己写的vector并不好,对自定义类型的顺序表的修改有许多问题
{
vector<string> v1;
v1.push_back("111");
vector<string> v2;
v2.push_back("222");
v2 = v1;
Print_Vector(v1);
Print_Vector(v2);
v2.insert(v2.begin(), "3");
Print_Vector(v1);
Print_Vector(v2);
}
void test11()//由此可以验证自己写的vector并不好,对自定义类型的顺序表的修改有许多问题
{
vector<int> v1;
v1.push_back(1);
v1.push_back(2);
v1.push_back(3);
v1.push_back(4);
v1.push_back(5);
v1.push_back(6);
v1.push_back(7);
v1.push_back(8);
vector<int>::iterator it = v1.begin() + 3;
v1.insert(it,100);//insert以后可能会进行扩容,此时迭代器失效,因为it还指向原来的位置
//vs的迭代器在erase后也会失效,vs就禁止使用了,因为用的不是原生指针,但是g++用的是原生指针,就像我们写的
//vs下要更新后才能使用
Print_Vector(v1);
cout << *it << endl;
}
void test12()
{
vector<vector<int>> vv1;
vector<int> v1;
v1.push_back(1);
v1.push_back(2);
v1.push_back(3);
v1.push_back(4);
vector<int> v2;
v2.push_back(5);
v2.push_back(6);
v2.push_back(7);
v2.push_back(8);
vector<int> v3;
v3.push_back(8);
v3.push_back(7);
v3.push_back(6);
v3.push_back(5);
vv1.push_back(v1);
vv1.push_back(v2);
vv1.push_back(v3);
vector<vector<int>> vv2;
vv2 = vv1;
for (size_t i = 0; i < 3; i++)
{
for (size_t j = 0; j < 4; j++)
{
cout << vv2[i][j] << " ";
}
cout << endl;
}
cout << "-------------------" << endl;
delete[] vv1.begin();
for (size_t i = 0; i < 3; i++)
{
for (size_t j = 0; j < 4; j++)
{
cout << vv2[i][j] << " ";
}
cout << endl;
}
cout << "-------------------" << endl;
}
}