当前位置: 首页 > news >正文

C++:Vector类核心技术解析及其模拟实现

目录:

    • vector类
      • 一、 vector容器的基本概念
      • 二、vector创建对象的构造方式
      • 三、常用接口解析
        • 1.容量操作
        • 2.元素访问
        • 3.修改操作
        • 4.二维(多维)数组
      • 四、vector底层数据结构与动态扩容机制
        • 1. 核心数据结构
        • 2. 动态扩容机制
      • 五、vector模拟实现关键代码
        • 1. 基础框架
        • 2. 内存管理核心函数
        • 3. 元素访问与修改
      • 六、迭代器失效问题深度解析
        • 1. 失效场景
        • 2. 解决方案

C++:Vector类核心技术解析及其模拟实现

vector类

一、 vector容器的基本概念

vector是C++标准模板库(STL)中的动态数组容器,能够存储相同类型的元素。其核心特点包括:

  • 动态扩容:内存空间自动增长,无需手动管理。
  • 随机访问:支持通过下标(如v[i])快速访问元素,时间复杂度为O(1)。
  • 连续存储:元素在内存中连续排列,兼容C风格数组操作。

二、vector创建对象的构造方式

初始化方式语法示例功能描述
默认构造std::vector<T> v;创建空vector,元素类型为T,容量为0
列表初始化std::vector<T> v({a, b, c});使用花括号直接初始化元素,C++11引入
拷贝构造std::vector<T> v2(v1);通过另一个同类型vector复制所有元素
迭代器区间构造std::vector<T> v2(v1.begin(),v1.end());构造一个容器,其中包含与范围 [first,last] 一样多的元素,每个元素都按相同的顺序从该区域中的相应元素构造。
填充构造std::vector<T> v2(10,1);构造一个包含 10 个元素的容器,每个元素都是1.

在这里插入图片描述

代码示例:

// 默认构造
std::vector<int> v1; // 列表初始化
std::vector<int> v2 ({1, 2, 3}); // 拷贝构造
std::vector<int> v3(v2); //迭代器区间构造
int myints[] = {16,2,77,29};std::vector<int> v4 (myints, myints + sizeof(myints) / sizeof(int) );

列表初始化是C++11引入的 原型是
vector (initializer_list il, const allocator_type& alloc = allocator_type());
initializer_list是一个类,使用时要包含头文件 #include <initializer_list>
auto il = { 10, 20, 30 }; il就是一个initializer_list类型

区别:

std::vector<int> v2 ({1, 2, 3}); 
std::vector<int> v2 = {1, 2, 3}; 
std::vector<int> v2 {1, 2, 3}; 

在这里插入图片描述

三、常用接口解析

1.容量操作
接口参数返回值功能示例
resize(len)len:新长度void调整动态数组大小v.resize(3);
reserve(size)size:预留容量void预分配内存避免多次扩容v.reserve(100);
size()size_t返回动态数组大小v.size();
capacity()size_t返回空间总大小v.capacity;

resize();同string类一样,如果小于当前数组大小会缩容
对比string你会发现STL这些容器的有些接口名字相同,功能也类似,大大减小了我们的学习成本

2.元素访问

同string一样下标访问、范围for、迭代器访问,用法也类似,祥见上一篇文章string
在这里插入图片描述

其次值得注意的是vector不提供流插入运算符重载

3.修改操作

在这里插入图片描述
在这里插入图片描述

4.二维(多维)数组

以这道题为例:
在这里插入图片描述
在这里插入图片描述

class Solution 
{
public:vector<vector<int>>generate(int numRows){vector<vector<int>>vv;vv.resize(numRows,vector<int());for(size_t i = 0; i < numRows; ++i){vv[i].resize(i+1,1);}for(size_ti=2;i<vv.size();++i){for(size_tj=1;j<vv[i].size()-1;++j){vv[i][j]=vv[i-1][j]+vv[i-1][j-1];}}return vv;}
};

在这里插入图片描述

四、vector底层数据结构与动态扩容机制

1. 核心数据结构

vector通过三个指针实现动态数组管理:

template <class T>
class vector 
{
private:T* _start;// 指向数组首元素T* _finish;// 指向最后一个有效元素的下一位T* _end_of_storage;// 指向内存空间末尾
};
  • _finish - _start = 有效元素数量(size()
  • _end_of_storage - _start = 总容量(capacity()
  • 连续内存布局:兼容C风格数组操作,支持随机访问(O(1))
    在这里插入图片描述
2. 动态扩容机制

触发条件:当 size() == capacity() 时执行 push_backinsert 会触发扩容。

扩容流程

  1. 申请新内存空间(大小为原空间的k倍)
  2. 拷贝旧数据到新空间(深拷贝)
  3. 释放旧内存
  4. 更新三个指针的值

扩容策略对比

平台扩容因子优势劣势
GCC2倍时间复杂度低(均摊O(1))内存碎片率高
VS1.5倍内存复用率高,碎片少扩容次数稍多

五、vector模拟实现关键代码

1. 基础框架
template<class T>
class Vector 
{
public:typedef T* iterator;//迭代器iterator begin()const{return _start;}iterator end()const{return _finish;}Vector() : _start(nullptr),_finish(nullptr), _end_of_storage(nullptr) {}vector(int n, const T& value = T()){resize(n, value);}// 迭代器区间构造
template <class InputIterator>
Vector(InputIterator first, InputIterator last) 
{while (first != last) {push_back(*first);++first;}
}// 列表初始化(C++11)
Vector(std::initializer_list<T> il) 
{reserve(il.size());for (auto& e : il) push_back(e);
}//赋值重载
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 v;
}//析构
~vector()
{delete[] _start;_start = _finish = _end_of_storage = nullptr;
}
private:iterator _start;iterator _finish;iterator _end_of_storage;
};

注意:
我们自己写的迭代器区间构造又缺陷,如果我们的实例化类型不是迭代器类型,比如是int,那么我们解引用的时候就会出问题。
针对这个问题,库里使用一种名为"萃取"的技术,了解即可

2. 内存管理核心函数

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) {// 深拷贝(不能用memcpy)tmp[i] = _start[i];// 调用T的赋值运算符}delete[] _start;// 释放旧空间_start = tmp;_finish = _start + old_size;_end_of_storage = _start + n;}
}

在这里插入图片描述

resize():调整有效元素数量

void resize(size_t n, const T& val = T()) 
{if (n < size()) {// 缩容_finish = _start + n;} else {// 扩容+初始化reserve(n);while (_finish != _start + n) {*_finish = val;++_finish;}}
}
3. 元素访问与修改

operator[](支持const重载):

T& operator[](size_t pos) 
{assert(pos < size());return _start[pos];
}

push_back()(含扩容逻辑):

void push_back(const T& x) 
{if (_finish == _end_of_storage) {// 需扩容size_t new_cap = capacity() == 0 ? 4 : capacity() * 2;reserve(new_cap);}*_finish = x;// 尾部插入++_finish;
}

insert()(需处理迭代器失效):

iterator insert(iterator pos, const T& x) 
{
assert(pos >= _start && pos <= _finish);// 扩容前保存偏移量
size_t offset = pos - _start;
if (_finish == _end_of_storage) 
{reserve(capacity() == 0 ? 4 : capacity() * 2);pos = _start + offset;// 重定位pos
}// 后移元素
iterator end = _finish - 1;
while (end >= pos) 
{*(end + 1) = *end;--end;
}*pos = x;// 插入新元素
++_finish;
return pos;// 返回新位置的迭代器
}

pop_back()erase()

void pop_back() 
{if (_finish > _start) --_finish;
}iterator erase(iterator pos) 
{iterator begin = pos + 1;while (begin != _finish) {// 前移元素*(begin - 1) = *begin;++begin;
}--_finish;return pos;// 返回删除位置的下一位置
}

在这里插入图片描述
在这里插入图片描述

六、迭代器失效问题深度解析

1. 失效场景
操作失效原因影响范围
insert扩容导致内存重分配所有迭代器失效
erase元素前移覆盖被删位置被删位置及之后的迭代器
push_back尾部扩容所有迭代器可能失效
2. 解决方案
  • 重新赋值
auto it = v.begin();
while (it != v.end()) 
{if (*it == 3) {it = v.erase(it);// 接收erase返回的新迭代器} else {++it;}
}
  • 避免扩容后使用旧迭代器:在 insert/push_back 后更新迭代器(通过返回值或重新计算偏移量)。

http://www.dtcms.com/a/282085.html

相关文章:

  • 北京-4年功能测试2年空窗-报培训班学测开-第五十二天
  • 印章标注,支持圆形、方形印章,OCR图片识别
  • 可道云最新版1.60.02发布了,新增免费内网穿透插件
  • 041_多接口实现与冲突解决
  • DuckDB 高效导入 IPv6 地址数据的实践与性能对比
  • 创客匠人拆解:知识变现系统如何破解 “增长困局”?
  • GENERALIST REWARD MODELS: FOUND INSIDE LARGELANGUAGE MODELS
  • 从 CSV文件的加载、分区和处理 来理解 Spark RDD
  • 设计模式—初识设计模式
  • 【kubernetes】--安全认证机制
  • Linux4:线程
  • 前端技术之---应用国际化(vue-i18n)
  • UE5多人MOBA+GAS 24、创建属性UI(一)
  • ubuntu24 c++ 自定义目录编译opencv4.12
  • Ubuntu GRUB菜单密码重置教程
  • 电脑安装 Win10 提示无法在当前分区上安装Windows的解决办法
  • WPF+CEF 执行JS报错
  • 从零开始的云计算生活——番外3,LVS+KeepAlived+Nginx高可用实现方案
  • [1-01-01].第43节:常用类 - 比较器类 Comparator接口
  • 【DataWhale】快乐学习大模型 | 202507,Task02笔记
  • Grok 系列大模型:xAI 的智能宇宙探秘
  • web前端用MVP模式搭建项目
  • DNS防护实战:用ipset自动拦截异常解析与群联AI云防护集成
  • 用PyTorch手写透视变换
  • 【unitrix】 6.4 类型化数特征(t_number.rs)
  • Rust 基础大纲
  • AI产品经理面试宝典第27天:AI+农业精准养殖与智能决策相关面试题解答指导
  • 疗愈之手的智慧觉醒:Deepoc具身智能如何重塑按摩机器人的触觉神经
  • mongoDB集群
  • Jmeter+ant+jenkins接口自动化测试框架