<vector>

        在 C++ 中,vector是标准库(STL)提供的动态数组容器,属于序列容器的一种。它结合了静态数组的高效随机访问特性与动态扩容能力,是日常开发中最常用的容器之一。本文将详细解析其实现原理与常见操作。

vector 概述

vector本质是动态数组,支持在运行时动态调整大小。其核心特点包括:

  • 元素在内存中连续存储,支持随机访问(时间复杂度 O (1));
  • 尾部插入 / 删除元素效率高(不扩容时 O (1));
  • 中间插入 / 删除元素效率低(需移动后续元素,O (n));
  • 自动管理内存,无需手动分配 / 释放。

使用前需包含头文件:#include <vector>,且位于std命名空间中。

vector 实现原理

<vector>已经十分成熟有几千行代码,熟悉使用即可,以下仅方便理解,不是原代码。

vector的底层通过动态分配的数组存储元素,并通过三个核心指针管理内存:

  • begin:指向数组中第一个元素的地址;
  • end:指向数组中最后一个元素的下一个位置(即当前元素末尾);
  • _end_of_storage:指向数组内存块的末尾(即容量末尾)。

通过这三个指针可快速计算:

  • 大小(size):end - begin(当前元素个数);
  • 容量(capacity):_end_of_storage - begin(当前可容纳的最大元素数)。 

包含大小和容量的简化版

template<typename T>
class vector {
private:
    T* data;           // 指向动态数组的指针
    size_t size;       // 当前元素数量
    size_t capacity;   // 当前分配的内存容量
};

现在忘掉之前的一切,只记住简化版即可

动态扩容机制

当插入元素导致size超过capacity时,vector会触发扩容,步骤如下:

  1. 分配新内存:新容量通常为原容量的 1.5 倍(VS 编译器)或 2 倍(GCC 编译器);
  2. 复制元素:将原数组元素复制(或移动)到新内存;
  3. 释放旧内存:销毁原数组元素并释放旧内存;
  4. 更新指针:指向新内存的对应位置。

注意:扩容后,原有的迭代器、指针、引用会失效(内存地址已改变)。

常见操作详解

1. 创建与初始化

vector支持多种初始化方式,适应不同场景:

方式示例说明
默认构造vector<int> v;空 vector,size=0,capacity=0
指定大小与初始值vector<int> v(5, 10);5 个元素,每个值为 10(size=5,capacity=5)
数组初始化int arr[] = {1,2,3}; vector<int> v(arr, arr+3);用数组 [arr, arr+3) 范围初始化
拷贝构造vector<int> v2(v1);复制 v1 的所有元素(深拷贝)
移动构造vector<int> v2 = move(v1);转移 v1 的资源(v1 此后为空)
列表初始化vector<int> v{1,2,3,4};用初始化列表直接赋值(C++11)
2. 元素访问

vector提供多种访问元素的方式,各有特点:

操作示例说明
operator[]v[2] = 10;访问索引为 2 的元素,不检查越界(越界行为未定义)
at()v.at(2) = 10;访问索引为 2 的元素,越界时抛出out_of_range异常
front()int x = v.front();返回第一个元素的引用(容器非空)
back()int y = v.back();返回最后一个元素的引用(容器非空)
data()int* p = v.data();返回指向底层数组的指针(可直接操作原始数组)
3. 修改操作

修改操作主要用于添加、删除或替换元素:

操作示例说明
push_back(val)v.push_back(5);在尾部添加元素 val(可能触发扩容)
emplace_back(args...)v.emplace_back(5);在尾部直接构造元素(避免拷贝,比push_back高效)
pop_back()v.pop_back();删除尾部元素(size 减 1,capacity 不变)
insert(pos, val)v.insert(v.begin()+1, 10);在迭代器 pos 前插入 val,返回新元素的迭代器(可能扩容,pos 后迭代器失效)
erase(pos)auto it = v.erase(v.begin());删除 pos 位置的元素,返回下一个元素的迭代器(pos 后迭代器失效)
clear()v.clear();清空所有元素(size=0,但 capacity 不变)
4. 容量操作

容量操作用于管理vector的内存使用:

操作示例说明
size()int s = v.size();返回当前元素个数
capacity()int c = v.capacity();返回当前可容纳的最大元素数
empty()if (v.empty()) { ... }判断是否为空(size==0)
reserve(n)v.reserve(10);预留容量为 n(若 n > 当前 capacity 则扩容,不改变 size)
resize(n, val)v.resize(5, 0);调整 size 为 n(n > 原 size 则补 val;n < 原 size 则删除多余元素,可能改变 capacity)
shrink_to_fit()v.shrink_to_fit();缩减 capacity 至与 size 相等(C++11,释放多余内存)
5. 迭代器

迭代器是访问vector元素的通用方式,支持遍历、插入、删除等操作:

迭代器类型示例说明
正向迭代器begin() / end()遍历元素(从第一个到最后一个的下一个)
反向迭代器rbegin() / rend()反向遍历(从最后一个到第一个的前一个)
const 迭代器cbegin() / cend()只读访问(不允许修改元素)

迭代器失效场景

  • 扩容时:所有迭代器、指针、引用失效;
  • insert插入元素后:插入位置后的迭代器失效;
  • erase删除元素后:删除位置后的迭代器失效(返回的新迭代器有效)。

总结

  vector是 C++ 中最常用的动态数组容器,通过连续内存存储和动态扩容机制,平衡了效率与灵活性。掌握其实现原理(三个核心指针、扩容机制)和常见操作(初始化、访问、修改、容量管理),能帮助开发者更高效地使用vector,避免因迭代器失效或不当扩容导致的问题。

posted @ 2025-11-17 22:04  mc12356  阅读(61)  评论(0)    收藏  举报  来源