?个人主页: 起名字真南
?个人专栏:【数据结构初阶】 【C语言】 【C++】 【OJ题解】
目录
1. 引言2. 实现思路3. `vector` 容器的代码实现4. 代码详解4.1 构造与析构函数4.2 容量管理4.3 迭代器与访问操作4.4 增删操作 5.测试代码6. 时间和空间复杂度分析7. 总结
1. 引言
vector
是 C++ 标准模板库(STL)中最常用的动态数组容器。它不仅提供了自动扩容、快速访问、灵活增删等功能,还能高效地管理内存。本篇文章将带大家实现一个简化版的 vector
,包含动态扩容、元素插入删除、访问等操作,以此深入理解其内部实现原理,尤其是动态数组的管理机制。
2. 实现思路
我们将实现的 vector
具有如下核心功能:
3. vector
容器的代码实现
以下是完整的代码实现,功能完备,包含了构造、析构、拷贝、赋值重载、容量管理、增删操作和元素访问等基本操作:
#pragma once#include <iostream>#include <assert.h>namespace wzr { template<class T> class vector { public: typedef T* iterator; typedef const T* const_iterator; // 默认构造函数 vector() : _start(nullptr) , _finish(nullptr), _endOfStorage(nullptr) {} // 构造函数:构造n个value vector(size_t n, const T& value = T()) : _start(nullptr) , _finish(nullptr) , _endOfStorage(nullptr) { reserve(n); while (n--) { push_back(value); } //其实我们会发现这两串代码会有一些冗余,当我们使用vector(10,1) //编译器在编译的时候就已经将T实例化成int类型, //并且编译器会认为10,1是int,如果两个类型一致就会选择是区间构造,会报错。 vector(int n, const T & value = T()):_start(new T[n]), _finish(_start + n), _endOfStorage(_finish){reserve(n);for (int i = 0; i < n; i++){_start[i] = value;}} // 拷贝构造函数 vector(const vector<T>& v) : _start(nullptr) , _finish(nullptr) , _endOfStorage(nullptr) { reserve(v.capacity()); iterator it = begin(); const_iterator vit = v.cbegin(); while (vit != v.cend()) { *it++ = *vit++; } _finish = it; } //如果使用iterator作为迭代器进行区间初始化构造, //那么容器就是能是vector//重新声明迭代器,迭代区间[first, last)可以是任意容量的迭代器template<class InputIterator>vector(InputIterator first, InputIterator last){while (first != last){push_back(*first);++first;}} // 赋值操作符重载(采用拷贝交换优化) vector<T>& operator=(vector<T> v) { swap(v); return *this; } // 析构函数 ~vector() { if (_start) { delete[] _start; _start = _finish = _endOfStorage = nullptr; } } // 迭代器 iterator begin() { return _start; } iterator end() { return _finish; } const_iterator cbegin() const { return _start; } const_iterator cend() const { return _finish; } // 容量管理 size_t size() const { return _finish - _start; } size_t capacity() const { return _endOfStorage - _start; } bool empty() const { return _start == _finish; } // 预留空间 void reserve(size_t n) { if (n > capacity()) { size_t oldSize = size(); T* tmp = new T[n]; if (_start) { for (size_t i = 0; i < oldSize; i++) { tmp[i] = _start[i]; } delete[] _start; } _start = tmp; _finish = _start + oldSize; _endOfStorage = _start + n; } } // 改变大小 void resize(size_t n, const T& value = T()) { if (n <= size()) { _finish = _start + n; } else { if (n > capacity()) { reserve(n); } iterator it = _finish; _finish = _start + n; while (it != _finish) { *it = value; it++; } } } // 元素访问 T& operator[](size_t pos) { assert(pos < size()); return _start[pos]; } const T& operator[](size_t pos) const { assert(pos < size()); return _start[pos]; } T& front() { return *_start; } const T& front() const { return *_start; } T& back() { return *(_finish - 1); } const T& back() const { return *(_finish - 1); } // 增删操作 void push_back(const T& value) { insert(end(), value); } void pop_back() { erase(end() - 1); } // 交换两个vector void swap(vector<T>& v) { std::swap(_start, v._start); std::swap(_finish, v._finish); std::swap(_endOfStorage, v._endOfStorage); } // 插入 iterator insert(iterator pos, const T& x) { assert(pos <= _finish); if (_finish == _endOfStorage) { size_t newcapacity = (capacity() == 0 ? 1 : 2 * capacity()); reserve(newcapacity); pos = _start + size(); } iterator end = _finish - 1; while (end >= pos) { *(end + 1) = *end; --end; } *pos = x; ++_finish; return pos; } // 删除 iterator erase(iterator pos) { iterator begin = pos + 1; while (begin != end()) { *(begin - 1) = *begin; begin++; } --_finish; return pos; } private: iterator _start; // 数据起始指针 iterator _finish; // 有效数据的结束指针 iterator _endOfStorage; // 总容量的结束指针 };}
4. 代码详解
4.1 构造与析构函数
vector()
:默认构造函数,初始化指针为 nullptr
,用于构造空的 vector
。vector(size_t n, const T& value = T())
:构造一个大小为 n
的 vector
,并用 value
初始化每个元素。调用 reserve(n)
分配空间,再通过 push_back
插入元素。vector(const vector<T>& v)
:拷贝构造函数。分配与 v
相同的空间后,逐个拷贝 v
中的元素。vector(InputIterator first,InputIterator last)
:使用迭代器区间去构造函数。~vector()
:析构函数。释放动态分配的内存,并将所有指针置为 nullptr
。 4.2 容量管理
reserve(size_t n)
:扩容函数。若 n
大于当前容量,则分配一个大小为 n
的新空间,将原数据拷贝至新空间,并释放旧空间。resize(size_t n, const T& value = T())
:调整 vector
大小。若 n
小于当前大小,则只需调整 _finish
。若 n
大于容量,则扩容并初始化新增元素。 4.3 迭代器与访问操作
begin()
和 end()
:返回 _start
和 _finish
,用于迭代 vector
。operator[]
:通过下标访问元素,并通过 assert
检查越界访问。front()
和 back()
:返回首尾元素的引用,支持首尾元素的快速访问。 4.4 增删操作
push_back(const T& value)
:在尾部插入元素 value
。若容量不足,调用 reserve
扩容。pop_back()
:删除最后一个元素,通过调整 _finish
指针实现。insert(iterator pos, const T& x)
:在指定位置插入元素 x
。若容量不足,则扩容;随后将 [pos, end)
的数据右移,腾出插入位置。erase(iterator pos)
:删除指定位置的元素。将 [pos + 1, end)
的数据左移一位以覆盖删除位置,更新 _finish
指针。 5.测试代码
#include"Vector.h"namespace wzr{void Test01(){vector<int> v1;vector<int> v2(10, 6);int array[] = { 1,2,3,4,5 };vector<int> v3(array, array + sizeof(array) / sizeof(array[0]));vector<int> v4(v3);for (size_t i = 0; i < v2.size(); i++){cout << v2[i] << " ";}cout << endl;auto it = v3.begin();while (it != v3.end()){cout << *it << " ";it++;}cout << endl;for (auto itt : v4){cout << itt << " ";}cout << endl;}void Test02(){vector<int> v;v.push_back(1);v.push_back(2);v.push_back(3);v.push_back(4);v.push_back(5);cout << v.size() << endl;cout << v.capacity() << endl;cout << v.front() << endl;cout << v.back() << endl;cout << v[0] << endl;for (auto e : v){cout << e << " ";}cout << endl;v.pop_back();v.pop_back();v.insert(v.begin(), 0);for (auto e : v){cout << e << " ";}cout << endl;v.erase(v.begin() + 1);for (auto e : v){cout << e << " ";}cout << endl;}}int main(){//wzr::Test01();wzr::Test02();return 0;}
6. 时间和空间复杂度分析
push_back
:均摊时间复杂度为O(1),因为扩容后插入操作是常数时间的。pop_back
:O(1)。resize
:O(n)。insert
和 erase
:最坏情况时间复杂度为O(n),因为需要移动大量数据。 7. 总结
通过对各个函数的详细解析,我们手动实现了一个简化版的 vector
,展示了 C++ 标准库中 vector
的核心功能。希望通过这篇文章,大家能更好地理解 vector
容器