前言
在C++标准模板库(STL)中,vector是最常用的容器之一,它是一个动态数组,能够自动管理内存,支持随机访问。今天我们就来手把手实现一个简化版的vector,帮助初学者理解其内部原理。
基本结构
首先我们定义vector类的基本框架:
namespace yzq {
template<class T>
class vector {
public:
typedef T* iterator; // 定义迭代器
typedef const T* const_iterator; // 常量迭代器
private:
iterator _start = nullptr;
iterator _finish = nullptr;
iterator _end_of_storage = nullptr;
};
}
这里我们使用三个指针来管理动态数组:
-
_start:指向数组的起始位置 -
_finish:指向最后一个元素的下一个位置 -
_end_of_storage:指向分配内存的末尾
迭代器
迭代器让我们能够像使用指针一样遍历容器:
iterator begin() {
return _start;
}
iterator end() {
return _finish;
}
const_iterator begin() const{
return _start;
}
const_iterator end() const{
return _finish;
}
内存管理
reserve函数
reserve函数用于预分配内存:
// 开内存
void reserve(size_t n) {
if (n > capacity()) {
size_t old_size = size();
T* tmp = new T[n];
for (size_t i = 0; i < old_size; i++) {
tmp[i] = _start[i];
}
delete[] _start;
_start = tmp;
_finish = tmp + old_size;
_end_of_storage = tmp + n;
}
}
构造函数
我们的vector支持多种构造方式:
默认构造
// C++11支持的前置生成默认构造
vector() = default;
初始化构造
// 初始化构造
vector(size_t n, const T& value = T())
:_start(nullptr), _finish(nullptr), _end_of_storage(nullptr) {
reserve(n);
for (size_t i = 0; i < n; i++) {
_start[i] = value;
}
_finish = _start + n;
}
// 为整数类型提供特别的初始化构造,避免与通用区间构造混淆
vector(int n, int value = 0)
:_start(nullptr), _finish(nullptr), _end_of_storage(nullptr) {
reserve(n);
for (int i = 0; i < n; i++) {
_start[i] = value;
}
_finish = _start + n;
}
区间构造
// 区间构造(针对vector类型)
vector(const_iterator first, const_iterator last)
:_start(nullptr), _finish(nullptr), _end_of_storage(nullptr) {
size_t n = last - first;
reserve(n);
for (size_t i = 0; i < n; i++) {
_start[i] = first[i];
}
_finish = _start + n;
}
// 区间构造(通用版)
template<class InputIterator>
vector(InputIterator first, InputIterator last)
:_start(nullptr), _finish(nullptr), _end_of_storage(nullptr) {
while (first != last) {
push_back(*first);
first++;
}
}
拷贝构造
// 拷贝构造(深拷贝)
vector(const vector<T>& v)
:_start(nullptr), _finish(nullptr), _end_of_storage(nullptr) {
reserve(v.capacity());
size_t i;
for (i = 0; i < v.size(); i++) {
push_back(v[i]);
}
}
基本操作
容量相关
size_t size() const {
return _finish - _start;
}
size_t capacity() const {
return _end_of_storage - _start;
}
元素访问
T& operator[](size_t i) {
assert(i < size());
return _start[i];
}
const T& operator[](size_t i) const {
assert(i < size());
return _start[i];
}
修改操作
尾插和尾删
// 尾插
void push_back(const T& x) {
// 满了先扩容
if (_finish == _end_of_storage) {
reserve(capacity() == 0 ? 4 : 2 * capacity()); // 2倍扩
}
*_finish = x;
_finish++;
}
// 尾删
void pop_back() {
assert(size() > 0);
_finish--;
}
插入和删除
// 插入
iterator insert(iterator pos, const T& x) {
assert(pos >= _start && pos <= _finish);
// 满了先扩容
if (_finish == _end_of_storage) {
size_t len = pos - _start; // 先计算原来的位置
reserve(capacity() == 0 ? 4 : 2 * capacity()); // 2倍扩
pos = _start + len; // 更新pos,避免迭代器失效
}
// 挪动数据
iterator end = _finish;
while (end > pos) {
*(end) = *(end - 1);
end--;
}
*pos = x;
_finish++;
return pos;
}
// 指定位置删除
iterator erase(iterator pos) {
assert(pos >= _start && pos < _finish);
// 挪动数据
iterator start = pos;
while (start < _finish - 1) {
*(start) = *(start + 1);
start++;
}
_finish--;
return pos;
}
调整大小
void resize(size_t n, const T& value = T()) {
// 小于当前元素个数即为删除元素,大于则添加元素
if (n < size()) {
_finish = _start + n;
}
else {
reserve(n);
while (_finish < _start + n) {
*_finish = value;
_finish++;
}
}
}
其他操作
// 清除数据
void clear() {
_finish = _start;
}
// 交换
void swap(vector<T>& v) {
std::swap(_start, v._start);
std::swap(_finish, v._finish);
std::swap(_end_of_storage,v._end_of_storage);
}
// 现代写法(注意一定得是传值构造)
vector<T>& operator=(vector<T> v) {
swap(v);
return *this;
}
工具函数
// 打印vector
void print_vector() const {
auto it = begin();
while (it != end()) {
std::cout << *it << " ";
it++;
}
std::cout << std::endl;
}
析构函数
// 析构
~vector() {
delete[] _start;
}
测试代码
void TestVector() {
yzq::vector<int> a;
a.push_back(1);
a.push_back(2);
a.push_back(3);
a.push_back(4);
a.push_back(5);
a.print_vector();
for (int i = 0; i < a.size(); i++) {
cout << a[i] << " ";
}
cout << endl;
yzq::vector<int> b(a.begin()+1, a.end()); // 区间拷贝
b.print_vector();
yzq::vector<int> c(b); // 深度拷贝
c.print_vector();
a.resize(1);
a.print_vector();
a.resize(10, 2);
a.print_vector();
}
int main() {
TestVector();
}