实现了vector容器的主要函数接口,简单底层实现了一下vector。
namespace nn
{
//模拟实现vector
template<class T>
class vector
{
public:
typedef T* iterator;
typedef const T* const_iterator;
//默认成员函数
vector(); //构造函数
vector(size_t n, const T& val); //构造函数
template<class InputIterator>
vector(InputIterator first, InputIterator last); //构造函数
vector(const vector<T>& v); //拷贝构造函数
vector<T>& operator=(const vector<T>& v); //赋值运算符重载函数
~vector(); //析构函数
//迭代器相关函数
iterator begin();
iterator end();
const_iterator begin()const;
const_iterator end()const;
//容量和大小相关函数
size_t size()const;
size_t capacity()const;
void reserve(size_t n);
void resize(size_t n, const T& val = T());
bool empty()const;
//修改容器内容相关函数
void push_back(const T& x);
void pop_back();
void insert(iterator pos, const T& x);
iterator erase(iterator pos);
void swap(vector<T>& v);
//访问容器相关函数
T& operator[](size_t i);
const T& operator[](size_t i)const;
private:
iterator _start; //指向容器的头
iterator _finish; //指向有效数据的尾
iterator _endofstorage; //指向容器的尾
};
}
#define _CRT_SECURE_NO_WARNINGS 1
namespace nn
{
template<typename T>//模板要定义在类外
class vector
{
public:
//默认成员函数
//构造函数1:无参构造函数
//使用:vector v1;
// vector v2
vector()
:_start(nullptr)
,_finish(nullptr)
,_endofstorage(nullptr)
{}
//构造函数2:迭代器区间进行构造
//使用:string s("abcdef");
//vector v(s.begin(),s.end());使用迭代器拷贝构造string对象的内容
//vector v(v1.begin,v1.end());
template<class InputInterator>//函数模板
vector(InputInterator first,InputInterator last)
:_start(nullptr)
, _finish(nullptr)
, _endofstorage(nullptr)
{
//将迭代器区间在[first,last)的数据一个个尾插到容器当中
while (first != last)
{
push_back(*first);
first++;
}
}
//构造函数3:构造有n个val的vector
//需要多重载一个函数,否则vector v1(10,1)
//由于10是int类型,这里会出现隐式类型转换
//而上面的迭代器区间构造更符合两个整型,所以编译器会优先选择上面的进行构造
//
vector(size_t n, const T& val)
:_start(nullptr)
, _finish(nullptr)
, _endofstorage(nullptr)
{
reserve(n);//先开n个空间
for (size_t i = 0; i < n; i++)
{
push_back(val);
}
}
vector(int n, const T& val)
:_start(nullptr)
, _finish(nullptr)
, _endofstorage(nullptr)
{
reserve(n);//先开n个空间
for (size_t i = 0; i < n; i++)
{
push_back(val);
}
}
//拷贝构造函数
//传统写法
//vector(const vector& v)
// :_start(nullptr)
// ,_finish(nullptr)
// ,_endofstorage(nullptr)
//{
// _start = new T[v.capacity()];//先开辟一块一样大小的空间
// for (size_t i = 0; i < v.size(); i++)
// {
// _start[i] = v._start[i];
// }
// _finish = _start + v.size();
// _endofstorage = _start + v.capacity();
//}
//现代写法
vector(const vector<T>& v)
:_start(nullptr)
, _finish(nullptr)
, _endofstorage(nullptr)
{
reserve(v.capacity());
for (auto e : v)
{
push_back(e);
}
}
//赋值运算符重载函数
//传统写法
//vector& operator=(const vector& v)
//{
// if (this != &v)
// {
// delete[] _start;
// _start = new T[v.capacity()]; //开辟一块和容器v大小相同的空间
// for (size_t i = 0; i < v.size(); i++) //将容器v当中的数据一个个拷贝过来
// {
// _start[i] = v[i];
// }
// _finish = _start + v.size(); //容器有效数据的尾
// _endofstorage = _start + v.capacity(); //整个容器的尾
// }
// return *this;
//}
//现代写法
vector<T>& operator=(vector<T> v)//形参是实参的一份临时拷贝,间接调用vector的拷贝构造函数
{
swap(v);
return *this;
}
//析构函数
~vector()
{
if (_start)
{
delete[] _start;
_start = nullptr;
_finish = nullptr;
_endofstorage = nullptr;
}
}
//迭代器的底层用指针实现
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;
}
void reserve(size_t n)
{
if (n > capacity())
{
T* tmp = new T[n];
/*1)在进行操作之前需要提前记录当前容器当中有效数据的个数。
因为我们最后需要更新_finish指针的指向,而_finish指针的指向就等于_start指针加容器当中有效数据的个数,
当_start指针的指向改变后我们再调用size函数通过_finish - _start计算出的有效数据的个数就是一个随机值了。*/
size_t oldsize = size();
if (_start)//如果原来的空间数据不为空
{
//不能用memcpy的原因在于:若容器存的是string类对象,
//没有将string类对象的_str指向的字符串也进行深拷贝,并且在delete,释放原数据时,_str的数据也会被释放(会自动调用string的析构函数)
//所以需要用赋值,将原来的string类对象,包括对象中的数据都深拷贝一份
//memcpy(tmp,_start,sizeof(T)*oldsize);
for (size_t i = 0; i < oldsize; ++i)//将原来的数据拷贝到新空间,并释放旧空间
{
tmp[i] = _start[i];
}
delete[] _start;
}
_start = tmp;
_finish = _start + oldsize;
_endofstorage = _start + n;
}
}
void resize(size_t n, const T& val = T())//int()=0
{
//减少有效字符个数
if (n < size())
{
_finish = _start + n;
}
else
{
if (n > capacity())
{
reserve(n);
}
while (_finish < _start + n)
{
*_finish = val;
++_finish;
}
}
}
bool empty() const
{
return _start == _finish;
}
//修改容器内容相关函数
void push_back(const T& x)
{
//检查容量
if (_finish == _endofstorage)
{
size_t newcapacity = capacity() == 0 ? 4 : 2 * capacity();
reserve(newcapacity);
}
*_finish = x;
_finish++;
}
void pop_back()
{
assert(!empty());
--_finish;
}
//迭代器失效:野指针问题
void insert(iterator pos, const T& val)
{
assert(pos >= _start);
assert(pos <= _finish);
if (_finish == _endofstorage)
{
//由于扩容后,迭代器pos可能会失效
size_t len = pos - _start;
size_t newcapacity = capacity() == 0 ? 4 : 2 * capacity();
reserve(newcapacity);
//所以扩容后更新一下pos的位置
pos = _start + len;
}
//从pos位置开始,向后挪动出一个空位
iterator end = _finish;
while (end>pos)
{
*end = *(end-1);
end--;
}
*pos = val;
_finish++;
}
iterator erase(iterator pos)
{
assert(pos >= _start);
assert(pos < _finish);
assert(!empty());
iterator end = pos + 1;
while (end!=_finish)
{
*(end - 1) = *end;
end++;
}
_finish--;
//迭代器失效问题,解决方法返回pos位置
return pos;
}
void swap(vector<T>& v)
{
std::swap(_start, v._start);
std::swap(_finish, v._finish);
std::swap(_endofstorage, v._endofstorage);
}
void clear()
{
_finish = _start;
}
//访问容器相关函数
T& operator[](size_t pos)
{
assert(pos < size());
return _start[pos];
}
const T& operator[](size_t pos) const
{
assert(pos < size());
return _start[pos];
}
private:
// 成员变量
iterator _start;//指向容器的头,相当于begin()
iterator _finish;//指向有效元素的尾,相当于size()
iterator _endofstorage;//指向容器的尾,相当于capacity()
};
}
#define _CRT_SECURE_NO_WARNINGS 1
#include
#include
#include
#include
using namespace std;
#include"vector.h"
int main()
{
//捕捉异常
try
{
nn::test_vector6();
}
catch(const exception& e)
{
cout << e.what() << endl;
}
return 0;
}