文章目录
vector和我们学数据结构时候的顺序表差不多,不过STL库里面的vector给我们提供了很多的接口函数,十分方便。对于各接口的调用这里就不详细讲解了,用到的时候不熟悉可以去官网查一下。这篇文章主要讲讲 个人对vector模拟实现的方法
Constructors(构造函数)
vector是一个模板类,可以存储不同类型的数据。先来看看官方的几种构造法方法
因为vector是一个模板类,所以在定义类时要用模板的格式。在vector中可以简单的定义三个类变量,全部用模板类型的指针类型
iterator _start;//首地址
iterator _finish;//最后一位有效数据的后一位地址
iterator _endofstorage;//容量的最后一位地址
template<class T>
class myvector {
public:
typedef T* iterator;
typedef const T* const_iterator;
private:
iterator _start;//首地址
iterator _finish;//最后一位有效数据地址
iterator _endofstorage;//容量的最后一位地址
};
myvector()
定义好变量后,先实现一个无参的构造函数。因为变量都是指针类型,所以一开始我们可以将它们初始化为nullptr
myvector()
:_start(nullptr)
, _finish(nullptr)
,_endofstorage(nullptr)
{
}
myvector(int n, const T& val = T())
再来实现一个跟库里面一样的,可以指定对象开辟的空间大小,并把指定值填入每一个空间中
myvector(int n, const T& val = T())
:_start(nullptr)
, _finish(nullptr)
, _endofstorage(nullptr)
{
reserve(n);
for (int i = 0; i < n; i++)
push_back(val);
}
push_back的实现下面再将。
注意:这个的缺省值不能用0或者" ",因为类型T没有确定,有可能会是我们自定义的类型,所以缺省值要使用T类型的默认初始值。参数中的n为什么不用size_t类型呢,下面会谈到
myvector(InputIterator first, InputIterator last)
接下来库里面的第三个构造函数,指定一段区间,并将这段区间的所有数值赋值到对象中。因为是一段区间,所以参数传的是指针,但是由于类型没有确定,所以要使用模板函数
template <class InputIterator>
myvector(InputIterator first, InputIterator last)
:_start(nullptr)
, _finish(nullptr)
, _endofstorage(nullptr)
{
while (first != last) {
push_back(*first);
first++;
}
}
为什么上面讲的第二个构造不使用size_t类型呢,就是因为第三个区间的构造传的参数是指针类型,如果第二个参数使用的是size_t类型,那么当我们构造传参时,编译器就不知道去匹配哪一个构造函数了。所以为了避免冲突,第二个构造我们使用int类型参数。
拷贝构造
接下来实现拷贝构造函数,因为有了上面的区间构造函数后,我们只需要创建一个临时的对象,然后和原对象交换一下后就可以了。需要注意的是,交换的时候要将地址交换才不会出现野指针的情况
myvector(const myvector<T>& v)
:_start(nullptr)
, _finish(nullptr)
, _endofstorage(nullptr)
{
myvector<int> tmp(v.begin(), v.end());
swap(tmp);
}
交换函数
交换地址就可以直接实现了
void swap(myvector<T>& v) {
std::swap(_start, v._start);
std::swap(_finish, v._finish);
std::swap(_endofstorage, v._endofstorage);
}
myvector< T >& operator=(myvector< T > v)
按照我们的使用习惯,一般都会有对象给对象赋值,所以肯定少不了实现 =运算符重载了。因为形参的改变不会影响实参,所以我们只需要形参对象和原对象交换一下即可
myvector<T>& operator=(myvector<T> v) {