目录
vector各函数接口总览
namespace Russ_Leo
{
//模拟实现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; //指向容器的尾
};
}
vector当中的成员变量介绍
在 vector
中有三个成员变量:_start、_finish 和 _endofstorage。
_start指向容器的头,_finish指向容器当中有效数据的尾,_endofstorage指向整个容器的尾。
默认成员函数
构造函数1
vector
首先支持一个无参的构造函数。对于这个构造函数,我们可以直接将对象的三个成员变量都初始化为 空指针。
//构造函数1
vector()
:_start(nullptr)
, _finish(nullptr)
, _endofstorage(nullptr)
{}
构造函数2
此外,vector
还支持使用一段迭代器区间来构造对象。由于这个迭代器区间可以是其他容器的迭代器区间,也就是说,该函数接收到的迭代器类型是不确定的,因此我们需要将该构造函数设计为一个函数模板。在函数体内,我们只需将该迭代器区间的数据逐个尾插到容器中即可。
//构造函数2
template<class InputIterator> //模板函数
vector(InputIterator first, InputIterator last)
:_start(nullptr)
, _finish(nullptr)
, _endofstorage(nullptr)
{
//将迭代器区间在[first,last)的数据一个个尾插到容器当中
while (first != last)
{
push_back(*first);
first++;
}
}
构造函数3
另外,vector
还支持构造包含n个值为val的容器。对于这个构造函数,我们可以先使用 reserve
函数将容器的容量设置为 n,然后使用 push_back
函数尾插 n 个值为 val 的数据到容器中。
//构造函数3
vector(size_t n, const T& val)
:_start(nullptr)
, _finish(nullptr)
, _endofstorage(nullptr)
{
reserve(n); //调用reserve函数将容器容量设置为n
for (size_t i = 0; i < n; i++) //尾插n个值为val的数据到容器当中
{
push_back(val);
}
}
注意:
- 该构造函数知道需要存储 n 个数据的空间,因此最好使用
reserve
函数一次性开辟足够的空间,避免在调用push_back
函数时多次增容,从而降低效率。- 该构造函数还需要实现两个重载函数。
vector(long n, const T& val)
:_start(nullptr)
, _finish(nullptr)
, _endofstorage(nullptr)
{
reserve(n); //调用reserve函数将容器容量设置为n
for (size_t i = 0; i < n; i++) //尾插n个值为val的数据到容器当中
{
push_back(val);
}
}
vector(int n, const T& val)
:_start(nullptr)
, _finish(nullptr)
, _endofstorage(nullptr)
{
reserve(n); //调用reserve函数将容器容量设置为n
for (int i = 0; i < n; i++) //尾插n个值为val的数据到容器当中
{
push_back(val);
}
}
可以看到,这两个重载函数的区别在于参数 n 的类型不同,但这是必要的。否则,当我们使用以下代码时,编译器会优先匹配构造函数2。
vector<int> v(5, 7); //调用构造函数3 ???
并且,由于构造函数2中对参数 first 和 last 进行了解引用操作,而 int
类型无法进行解引用操作,这会导致报错。
拷贝构造函数
vector
的构造函数涉及深拷贝问题,这里提供两种深拷贝的写法:
写法一:传统写法
传统的拷贝构造方法思想最为直观:首先开辟一块与该容器大小相同的空间,然后将容器中的数据逐个拷贝过来,最后更新 _finish 和 _endofstorage 的值。
//传统写法
vector(const vector<T>& v)
:_start(nullptr)
, _finish(nu