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<T>& 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。
template<class InputIterator>
vector(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;
}