> 技术文档 > C++之vector类的代码及其逻辑详解 (中)

C++之vector类的代码及其逻辑详解 (中)


我们已经初步认识了vetcor以及他的一些接口,那么接下来我们根据这些信息来实现vector以及其接口。

1. iterator

下面这两行不是必须的,但是建议写上,因为这样可以防止我们写出来的代码报入底层,对代码进行跟好的封装。

typedef T* iterator;

typedef const T* const_iterator;

2. private成员

  • _start:指向容器中第一个元素的位置
  • _finish:指向容器中最后一个元素的下一个位置。
  • _endofstorage:指向容器预留内存空间的末尾位置。

我们之所以要设计一个_endofstorage就是让_endofstorage和_finish在相遇的时候扩容。

private:iterator _start;iterator _finish;iterator _endofstorage;

3. 构造函数

这是vector的构造函数,即使用resize来对其直接进行初始化。

PS:假如说 vector里面存储的是 Date日期类对象,  构造 vector对象的时候,调用 vector(int n, const T& val = T()) ,此时 T的类型是 Date,调用的是Date的默认构造来生成缺省值,然后调用 resize(n,val)  此时 resize的时候,你传了val那就不会生成缺省的,如果不传,调用的也是Date的构造函数生成缺省参数。简单来说,在使用构造函数的时候里面这个resize的val调用的是默认构造,而不是说这个构造函数。

vector(size_t n, const T& val = T()){resize(n, val);}

4. 析构函数

这个就是析构函数,先通过delete清理掉数组,然后把三个指针都指向0。

~vector(){delete[] _start;_start = _finish = _endofstorage = 0;}

5. 拷贝构造

拷贝构造的作用不用多说,就是为了防止发生浅拷贝。

简单来说,就是先让this指针的_start指向一个新开辟好大小的数组,然后通过循环的方式进行赋值,接着让this指针的_finish和_endofstorage指向新的空间。

vector(const vector& v){_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();}

6. 默认构造函数

简单来说就是让这三个指针都先指向空。

默认构造函数和构造函数之间是不冲突的

vector():_start(nullptr), _finish(nullptr), _endofstorage(nullptr){}

7. 范围构造函数

这个叫做范围构造函数,简单来说就是通过两个指针分别指向一段元素范围,然后用那段范围来初始化vetcor。

templatevector(InputIterator first, InputIterator last){while (first != last){push_back(*first);++first;}}

8. begin()

这个就是返回vector的开头位置。

iterator begin(){return _start;}

这个的话也是返回vector的开头位置,只不过加了两个const,他们的作用如下:

const 位置 作用 目的 返回类型 const_iterator 限制迭代器的写权限 确保通过迭代器只能读取元素,不能修改(即使容器本身是非 const 的) 函数声明 () const 限制函数的修改权限 允许 const 对象调用该函数,并保证函数内部不会修改对象状态

一般来说这两个const是成对出现的。 

const_iterator begin() const{return _start;}

9. end()

返回最后一个的下一个。这种设计是为了方便迭代器进行遍历,比如说走一个循环,如果这个迭代器和end()的返回值相等那就代表遍历完了。

iterator end(){return _finish;}​const_iterator end() const{return _finish;}

10. erase()

这个函数用于销毁指定位置的元素。简单来说就是覆盖,把后面的一个一个往前挪,最后--_finish。

void erase(iterator pos){assert(pos >= _start && pos < _finish);iterator it = pos;while (it + 1 != _finish){*it = *(it + 1);++it;}--_finish;}

11.  pop_back()

 这个函数就是尾删,首先检查vector是不是空,如果是空那就报错,不是的话就直接--_finish,让用户访问不到就可以了。

void pop_back(){assert(_start != _finish);--_finish;}