跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客GitHub 精选镜像AI 生图工具UI配色美学隐私政策关于联系
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
C++算法

C++ STL vector 容器底层实现详解

C++ STL vector 容器基于动态数组实现,通过原生指针维护内存。核心成员包括_start、_finish、_end_of_storage。支持无参构造、指定数量构造及迭代器区间构造。拷贝构造函数与赋值运算符采用深拷贝策略,赋值重载使用 copy-and-swap 技巧保证异常安全。迭代器接口区分 const 与非 const 版本。容量管理涉及 reserve 扩容与 resize 调整大小。修改操作如 insert 和 erase 需处理数据搬移及迭代器失效问题。访问接口提供随机访问能力。

星星泡饭发布于 2026/3/22更新于 2026/7/332 浏览
C++ STL vector 容器底层实现详解

前言

在学习了 vector 类的基本使用的前提下,本文将重点分析 vector 类的常用接口及其应用实现。

一、vector 成员变量

vector 本质上是一个动态数组,通过原生指针来实现底层维护。为了使得 STL 接口调用的统一性,我们需要将原生指针重命名为迭代器。

其核心目的是:将数据结构(容器)与操作(算法)分离,并通过一种统一的接口(迭代器)将它们粘合在一起。

成员变量分析

template <class T> class vector {
public:
    // 将原生指针重命名为迭代器,实现接口统一
    typedef T* iterator;
    typedef const T* const_iterator;
private:
    iterator _start;       // 指向目前使用空间的头
    iterator _finish;      // 指向目前使用空间的尾
    iterator _end_of_storage; // 指向目前可用空间的尾
};

成员变量说明:

  1. iterator _start:指向目前使用空间的头
  2. iterator _finish:指向目前使用空间的尾
  3. iterator _end_of_storage:指向目前可用空间的尾

vector 内存布局

二、默认成员函数

2.1 无参构造

vector 默认支持无参构造函数,此时将对象的三个成员变量初始化为空指针。

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

2.2 构造函数:构造 n 个同类型的值

vector 的带参构造函数,作用是创建一个初始包含 n 个元素的 vector,并且将这些元素全部初始化为给定的 value。

函数原型: vector(size_t n, const T& value = T())

代码示例:

// 构造函数:构造出 n 个同类型的值
vector(size_t n, const T& value = T()) {
    // 避免多次扩容
    reserve(n);
    // 尾插元素
    for (size_t i = 0; i < n; i++) {
        push_back(value);
    }
}

解析:

  1. 核心优化 reserve(n):提前调用 reserve(n),一次性向系统申请好足够容纳 n 个元素的内存,可以直接把后续插入的扩容开销降为 0。
  2. 数据填充:在确保容量足够的前提下,循环 n 次,每次将 value 尾插到动态数组中,顺便更新内部维护的数组有效元素个数。

2.3 构造函数:迭代器区间构造

迭代器区间构造,接收任意一段具有迭代器特性的区间 [first, last),并把这段区间里的数据拷贝过来构造一个新的 vector。

函数原型: template<class InputIterator> vector(InputIterator first, InputIterator last)

代码实现:

template<class InputIterator>
vector(InputIterator first, InputIterator last) {
    while (first != last) {
        push_back(*first);
        ++first;
    }
}

使用示例:

// 1. 用数组的指针区间来构造
int arr[] = {1, 2, 3, 4, 5};
vector<int> v1(arr, arr + 5);

// 2. 用 std::list 的迭代器来构造
list<int> myList = {10, 20, 30};
vector<int> v2(myList.begin(), myList.end());

// 3. 用 std::string 的迭代器来构造字符
string str = "hello";
vector<char> v3(str.begin(), str.end());

原理: 原生指针 int* 支持 !=, *, ++ 操作,因此满足迭代器要求,编译器会自动实例化对应版本。

2.4 拷贝构造函数

自定义 vector 类的拷贝构造函数,作用是使用一个已经存在的 vector 对象(v1)来初始化一个新的 vector 对象(v2),需实现深拷贝。

函数原型: vector(const vector<T>& v)

现代写法:

vector(const vector<T>& v) {
    // 现代写法
    reserve(v.capacity());
    for (size_t i = 0; i < v.size(); i++) {
        push_back(v[i]);
    }
}

解析:

  1. reserve 实现了'空间独立':申请一块全新的堆内存,新对象与原对象物理隔离。
  2. push_back 实现了'数据复制':遍历源对象元素放入新空间,触发类型 T 的拷贝行为,保证深拷贝。

2.5 赋值重载函数

自定义 vector 类的赋值运算符重载函数,用于处理两个已存在对象间的赋值操作,例如:v1 = v2。

函数原型: vector<T>& operator=(vector<T> v)

代码实现:Copy-and-Swap

template<class T>
void vector<T>::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;
}

核心拆解:Copy-and-Swap 的三步魔法

  1. 传值触发拷贝构造:参数按值传递,自动调用拷贝构造函数生成临时对象 v。
  2. 交换指针:执行 swap(v),当前对象窃取临时对象的新内存,临时对象持有旧内存。
  3. 自动清理:函数结束,临时对象析构,释放旧内存。

三、迭代器相关函数

使用场景begin() / end() 返回类型可读 / 可写权限对应实现方式
普通 vector 对象iterator (即 T*)✅ 可读 ✅ 可写iterator begin()
iterator end()
const vector 对象const_iterator (即 const T*)✅ 只读 ❌ 不可写const_iterator begin() const
const_iterator end() const

3.1 begin

typedef T* iterator;
typedef const T* const_iterator;

iterator begin() { return _start; }
const_iterator begin() const { return _start; }

3.2 end

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

四、容量大小相关函数

4.1 size

size_t size() const { return _finish - _start; }

size 示意图

4.2 capacity

size_t capacity() const { return _end_of_storage - _start; }

capacity 示意图

4.3 reserve

函数原型: void reserve(size_t n);

功能: 当 n > capacity 时才扩容;当 n <= capacity 时不做任何操作。

代码实现:

template<class T>
void vector<T>::reserve(size_t n) {
    if (n > capacity()) {
        size_t oldsize = size();
        size_t newcapacity = n;
        T* tmp = new T[newcapacity];
        
        for (size_t i = 0; i < oldsize; i++) {
            tmp[i] = _start[i];
        }
        
        if (_start) delete[] _start;
        
        _start = tmp;
        _finish = tmp + oldsize;
        _end_of_storage = tmp + newcapacity;
    }
}

解析:

  1. 扩容门槛检查:判断传入容量是否大于当前容量。
  2. 保存 oldsize:防止更新 _start 后计算 size() 出错。
  3. 申请新空间与数据搬家:new 开辟新内存并拷贝旧数据。
  4. 释放旧空间:delete[] 释放原内存,防止泄漏。
  5. 更新内部指针:更新 _start, _finish, _end_of_storage。

4.4 resize

函数原型: void resize(size_t n, const T& val = T());

功能: 调整容器大小。若 n > size 则扩展并填充;若 n < size 则截断。

代码实现:

template<class T>
void vector<T>::resize(size_t n, const T& value) {
    reserve(n);
    if (n < size()) {
        _finish = _start + n;
    } else {
        while (_finish < _start + n) {
            *_finish = value;
            ++_finish;
        }
    }
}

解析:

  1. 兜底保护:先调用 reserve 确保物理空间足够。
  2. 缩小范围:直接移动 _finish 指针,不释放物理内存。
  3. 扩大范围:在预留空间中填充新元素。

4.5 empty

bool empty() { return _start == _finish; }

empty 示意图

五、修改容器相关函数

5.1 push_back

函数原型: void push_back(const T& x)

代码实现:

template<class T>
void vector<T>::push_back(const T& x) {
    if (_end_of_storage == _finish) {
        size_t newcapacity = capacity() == 0 ? 4 : capacity() * 2;
        reserve(newcapacity);
    }
    *(_finish) = x;
    ++_finish;
}

5.2 pop_back

函数原型: void pop_back();

代码实现:

template<class T>
void vector<T>::pop_back() {
    assert(!empty());
    if (_finish != _start) {
        --_finish;
    }
}

5.3 insert

函数原型: iterator insert(iterator pos, const T& x);

代码实现:

template<class T>
typename vector<T>::iterator vector<T>::insert(iterator pos, const T& x) {
    assert(pos >= _start);
    assert(pos <= _finish);
    
    if (_end_of_storage == _finish) {
        size_t abs_site = pos - begin();
        size_t newcapacity = capacity() == 0 ? 4 : capacity() * 2;
        reserve(newcapacity);
        pos = begin() + abs_site;
    }
    
    iterator last = end();
    while (last > pos) {
        *last = *(last - 1);
        --last;
    }
    
    *pos = x;
    ++_finish;
    return pos;
}

解析:

  1. 门禁检查:确保 pos 合法。
  2. 破解迭代器失效:扩容前记录相对偏移量,扩容后重新计算位置。
  3. 挪动数据:从后往前搬运,为新元素腾位。
  4. 返回值:返回新位置的迭代器。

5.4 erase

函数原型: iterator erase(iterator pos);

代码实现:

template<class T>
typename vector<T>::iterator vector<T>::erase(iterator pos) {
    assert(pos >= _start);
    assert(pos < _finish);
    
    iterator it = pos + 1;
    while (it != end()) {
        *(it - 1) = *it;
        ++it;
    }
    
    --_finish;
    return pos;
}

解析:

  1. 门禁检查:确保 pos 指向有效元素。
  2. 挪动数据:从前往后覆盖,填补空缺。
  3. 更新尾部:_finish 前移一位。
  4. 返回值:解决迭代器失效问题。

5.5 clear

函数原型: void clear();

代码实现:

void clear() {
    _finish = _start;
}

六、访问容器相关函数

6.1 operator[]

函数原型:

  1. T& operator[](size_t pos)
  2. const T& operator[](size_t pos) const

代码实现:

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

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

目录

  1. 前言
  2. 一、vector 成员变量
  3. 成员变量分析
  4. 二、默认成员函数
  5. 2.1 无参构造
  6. 2.2 构造函数:构造 n 个同类型的值
  7. 2.3 构造函数:迭代器区间构造
  8. 2.4 拷贝构造函数
  9. 2.5 赋值重载函数
  10. 三、迭代器相关函数
  11. 3.1 begin
  12. 3.2 end
  13. 四、容量大小相关函数
  14. 4.1 size
  15. 4.2 capacity
  16. 4.3 reserve
  17. 4.4 resize
  18. 4.5 empty
  19. 五、修改容器相关函数
  20. 5.1 push_back
  21. 5.2 pop_back
  22. 5.3 insert
  23. 5.4 erase
  24. 5.5 clear
  25. 六、访问容器相关函数
  26. 6.1 operator[]
  • 免费图片AI生成工具免费生成了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 免费图片视频在线生成30秒,将你的创意变成现实开始设计
  • X/Twitter免费视频下载器免登陆无限额度免费视频解析下载了解详情
  • 100+免费在线小游戏爽一把
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • Python 爬虫进阶:使用 Selenium 模拟浏览器操作
  • OpenCode 搭配 GitHub Copilot 打造高性价比 AI 编程方案
  • Java 全栈开发工程师实战面试:从基础到微服务
  • Flutter 接入 DeepSeek API 实现鸿蒙端 AI 对话与流式渲染
  • 企业级 Web 药店管理系统:SpringBoot+Vue+MyBatis+MySQL 架构设计
  • 数据结构实验:链队列的基本操作与实现
  • 基于腾讯云 HAI 与 DeepSeek 快速设计个人网页
  • MyBatis 扫描路径配置错误导致 Mapper 未找到问题排查
  • C++ ROS 回调函数中的对象生命周期陷阱:Use-After-Free 解析
  • FPGA 验证核心:全方位解析 AXI Verification IP (AXI VIP)
  • Python Django 音乐推荐系统:协同过滤算法与 Echarts 可视化
  • 个人如何利用 Python 爬虫技术实现变现
  • OpenClaw Docker 部署指南:集成飞书钉钉 QQ 机器人
  • Java SpringBoot 集成 OCR 构建企业级中间件服务
  • 数据结构基础:顺序表的定义与实现
  • AI 安全:基于对抗攻击的 Stable Diffusion 视觉提示词注入研究
  • Angular 应用 Chrome 高德地图定位超时问题解析与解决
  • Git 多人协作开发流程与冲突解决
  • AIGC 已步入落地阶段:2025 年六大技术趋势解析
  • Java IO 流进阶:字符流与字节流的核心差异与应用

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • Gemini 图片去水印

    基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online

  • Markdown转HTML

    将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online

  • HTML转Markdown

    将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online