说明:本文vector手撕仿照的是库函数实现,利用迭代器作为私有成员
private: typedef T* iterator;
iterator _start = nullptr;
iterator _finish = nullptr;
iterator _end_of_storage = nullptr;
(1)构造和析构注: // 构造采用默认参数,强制编译器生成
cpp
vector() = default;
~vector()
{
if (_start)
delete[] _start;
_start = _finish = _end_of_storage = nullptr;
cout << "~vector()" << endl;
}
(2)//拷贝构造和赋值重载
注: //拷贝构造直接尾插
//赋值重载直接现代写法
cpp
vector(const vector<T>& v)
{
reserve(v.capacity());
for (auto e : v)
{
push_back(e);
}
}
void swap(vector<T> v)
{
std::swap(_start,v._start);
std::swap(_finish,v._finish);
std::swap(_end_of_storage,v._end_of_storage);
}
vector<T>&operator=(vector<T> v)
{
swap(v);
return *this;
}
(3)//有效长度和开辟的大小空间
const size_t size()const { return _finish - _start; }
const size_t capacity()const { return _end_of_storage - _start; }
(4)//范围for,实现迭代器//这里使用T*充当迭代器,并不是所有的函数迭代器都是T*,迭代器可以屏蔽底层代码细节
cpp
iterator begin() { return _start; }
iterator end() { return _finish; }
const iterator begin() const{return _start;}
const iterator end() const {return _finish;}
(5)//插入和删除等相关函数
注: //库函数的参数为迭代器,因此会引入扩容和删除会引发迭代器失效问题,所以返回更新后的迭代器进行迭代器的更新
//扩容
//问题:
//(1)移动数据时,memcpy是浅拷贝,所以涉及到深拷贝的内容如vector<string>,析构原空间时会造成数据string的析构
//此时便会引发数据销毁等野指针问题
//(2)更新_finish时,由于_start已经指向新地方所以原size(_finish-_start)也会变化,所以要保存原数据的大小
cpp
void reserve(size_t n)
{
if (n > capacity())
{
iterator tmp = new T[n];
//保存原数据大小
size_t oldsize = size();
// memcpy(tmp,_start);
for (int i = 0; i < oldsize; i++)
{
tmp[i] = _start[i];
}
delete[] _start;
_start = tmp;
_finish = _start + oldsize;
_end_of_storage = _start + n;
}
}
iterator insert(iterator pos, const T& val)
{
assert(pos >= begin() && pos <= end());
size_t n = pos - _start;
if (_finish == _end_of_storage)
{
reserve(capacity() == 0 ? 4 : capacity() * 2);
pos = _start + n;
}
size_t end = size();
while (end > n)
{
_start[end] = _start[end - 1];
end--;
}
_start[n] = val;
_finish++;
return pos;
}
iterator erase(iterator pos)
{
assert(pos >= begin() && pos <= end());
size_t end = pos - _start + 1;
while (end < size())
{
_start[end - 1] = _start[end];
end++;
}
_finish--;
return pos;
}
void push_back(const T& val)
{
insert(end(), val);
}
void pop_back()
{
erase(end() - 1);
}
(6)所有代码:
cpp
#include <iostream>
#include <cassert>
using namespace std;
namespace Myvector
{
// 仿照库函数实现简易版的vector,学习并理解其底层原理
template <class T>
class vector
{
typedef T* iterator;
public:
// 构造与析构
// 构造采用默认参数,强制编译器生成
vector() = default;
~vector()
{
if (_start)
delete[] _start;
_start = _finish = _end_of_storage = nullptr;
cout << "~vector()" << endl;
}
//拷贝构造和赋值重载
//拷贝构造直接尾插
//赋值重载直接现代写法
vector(const vector<T>& v)
{
reserve(v.capacity());
for (auto e : v)
{
push_back(e);
}
}
void swap(vector<T> v)
{
std::swap(_start,v._start);
std::swap(_finish,v._finish);
std::swap(_end_of_storage,v._end_of_storage);
}
vector<T>&operator=(vector<T> v)
{
swap(v);
return *this;
}
//有效长度和开辟的大小空间
const size_t size()const { return _finish - _start; }
const size_t capacity()const { return _end_of_storage - _start; }
//范围for,实现迭代器
//这里使用T*充当迭代器,并不是所有的函数迭代器都是T*,迭代器可以屏蔽底层代码细节
iterator begin() { return _start; }
iterator end() { return _finish; }
const iterator begin() const{return _start;}
const iterator end() const {return _finish;}
//插入和删除等相关函数
//库函数的参数为迭代器,因此会引入扩容和删除会引发迭代器失效问题,所以返回更新后的迭代器进行迭代器的更新
//扩容
//问题:
//(1)移动数据时,memcpy是浅拷贝,所以涉及到深拷贝的内容如vector<string>,析构原空间时会造成数据string的析构
//此时便会引发数据销毁等野指针问题
//(2)更新_finish时,由于_start已经指向新地方所以原size(_finish-_start)也会变化,所以要保存原数据的大小
void reserve(size_t n)
{
if (n > capacity())
{
iterator tmp = new T[n];
//保存原数据大小
size_t oldsize = size();
// memcpy(tmp,_start);
for (int i = 0; i < oldsize; i++)
{
tmp[i] = _start[i];
}
delete[] _start;
_start = tmp;
_finish = _start + oldsize;
_end_of_storage = _start + n;
}
}
iterator insert(iterator pos, const T& val)
{
assert(pos >= begin() && pos <= end());
size_t n = pos - _start;
if (_finish == _end_of_storage)
{
reserve(capacity() == 0 ? 4 : capacity() * 2);
pos = _start + n;
}
size_t end = size();
while (end > n)
{
_start[end] = _start[end - 1];
end--;
}
_start[n] = val;
_finish++;
return pos;
}
iterator erase(iterator pos)
{
assert(pos >= begin() && pos <= end());
size_t end = pos - _start + 1;
while (end < size())
{
_start[end - 1] = _start[end];
end++;
}
_finish--;
return pos;
}
void push_back(const T& val)
{
insert(end(), val);
}
void pop_back()
{
erase(end() - 1);
}
private:
iterator _start = nullptr;
iterator _finish = nullptr;
iterator _end_of_storage = nullptr;
};
};
int main()
{
Myvector::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);
for (auto& e : v1)
{
cout << e << " ";
}
cout << endl;
v1.pop_back();
v1.pop_back();
v1.pop_back();
v1.pop_back();
for (auto& e : v1)
{
cout << e << " ";
}
cout << endl;
return 0;
}