【std::vector】size、capacity小结

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录


在C++的vector中,size(大小) capacity(容量)是两个核心概念,对应vector底层动态数组的元素数量内存空间上限 ,理解它们的区别和联系是高效使用vector的关键。下面用通俗比喻+定义+实例+内存机制的方式详细讲解。

一、核心比喻(快速理解)

vector想象成一个装小球的纸箱

  • size :纸箱里实际装的小球数量(能直接数到的小球个数)。
  • capacity :纸箱最大能容纳的小球数量(不换更大的纸箱时,最多能装这么多)。
  • 当小球数量(size)超过纸箱容量(capacity)时,你需要换一个更大的纸箱(扩容),把原来的小球全部搬过去,这个过程会消耗额外的时间和资源。

二、正式定义与特点

1. size(大小)
  • 定义vector实际存储的元素个数
  • 获取方式 :调用vector的成员函数size()
  • 合法访问范围 :可以通过下标[0, size()-1]访问元素(超出这个范围是未定义行为,除非用at()会抛异常)。
  • 影响size的操作 :所有会增加/删除元素 的操作都会改变size,比如:
    • 构造函数(vector<int> arr(5)size=5)。
    • push_back()(尾部加元素,size+1)、pop_back()(尾部删元素,size-1)。
    • resize(n)(直接设置sizen)。
    • insert()(插入元素,size增加)、erase()(删除元素,size减少)。
2. capacity(容量)
  • 定义vector当前分配的连续内存空间能容纳的最大元素个数(无需扩容时的上限)。
  • 获取方式 :调用vector的成员函数capacity()
  • 核心特点capacity ≥ size(永远成立,因为内存至少要装下当前所有元素)。
  • 影响capacity的操作 :只有内存重新分配 的操作才会改变capacity,比如:
    • reserve(n)(手动预留容量,若n>原capacity,则capacity变为n;否则无变化)。
    • 扩容 (当push_back()/insert()导致size超过capacity时,vector会自动分配更大的内存,capacity随之增大)。
    • shrink_to_fit()(C++11+,尝试将capacity缩小到与size相等,注意:这是请求而非强制,编译器可能忽略)。
    • 注意:pop_back()/erase()只会减少size不会改变capacity(内存不会自动释放,避免频繁的内存分配/释放)。

三、实例演示(直观看到变化)

通过代码一步步看sizecapacity的变化,以GCC编译器(扩容策略为原容量的1.5倍)为例(MSVC是2倍,规律一致)。

cpp 复制代码
#include <vector>
#include <iostream>
using namespace std;

int main() {
    // 1. 空vector:size=0,capacity=0(无元素,无内存)
    vector<int> arr;
    cout << "空vector:size=" << arr.size() << ",capacity=" << arr.capacity() << endl; // size=0,capacity=0

    // 2. push_back第一个元素:size=1,capacity=1(自动分配内存)
    arr.push_back(1);
    cout << "push_back(1):size=" << arr.size() << ",capacity=" << arr.capacity() << endl; // size=1,capacity=1

    // 3. push_back第二个元素:size=2,capacity=2(扩容到2,1*2=2)
    arr.push_back(2);
    cout << "push_back(2):size=" << arr.size() << ",capacity=" << arr.capacity() << endl; // size=2,capacity=2

    // 4. push_back第三个元素:size=3,capacity=3(GCC扩容到1.5倍:2*1.5=3)
    arr.push_back(3);
    cout << "push_back(3):size=" << arr.size() << ",capacity=" << arr.capacity() << endl; // size=3,capacity=3

    // 5. reserve(10):手动预留容量,size不变,capacity=10
    arr.reserve(10);
    cout << "reserve(10):size=" << arr.size() << ",capacity=" << arr.capacity() << endl; // size=3,capacity=10

    // 6. push_back(4):size=4,capacity仍为10(容量足够,无需扩容)
    arr.push_back(4);
    cout << "push_back(4):size=" << arr.size() << ",capacity=" << arr.capacity() << endl; // size=4,capacity=10

    // 7. pop_back():size=3,capacity仍为10(只删元素,不释放内存)
    arr.pop_back();
    cout << "pop_back():size=" << arr.size() << ",capacity=" << arr.capacity() << endl; // size=3,capacity=10

    // 8. resize(5):size=5(补充2个默认值0),capacity仍为10
    arr.resize(5);
    cout << "resize(5):size=" << arr.size() << ",capacity=" << arr.capacity() << endl; // size=5,capacity=10

    // 9. shrink_to_fit():尝试将capacity缩小到size=5
    arr.shrink_to_fit();
    cout << "shrink_to_fit():size=" << arr.size() << ",capacity=" << arr.capacity() << endl; // size=5,capacity=5

    return 0;
}

输出结果(GCC)

复制代码
空vector:size=0,capacity=0
push_back(1):size=1,capacity=1
push_back(2):size=2,capacity=2
push_back(3):size=3,capacity=3
reserve(10):size=3,capacity=10
push_back(4):size=4,capacity=10
pop_back():size=3,capacity=10
resize(5):size=5,capacity=10
shrink_to_fit():size=5,capacity=5

四、关键机制:vector的扩容原理

vector底层是连续的内存空间(和数组一样),这意味着它的内存地址是连续的,无法在原内存后直接追加空间(可能被其他数据占用)。因此:

  1. size超过capacity时,vector自动扩容
    • 步骤1:分配一块更大的连续内存(扩容策略:GCC是1.5倍,MSVC是2倍,目的是减少扩容次数)。
    • 步骤2:将原内存中的所有元素拷贝/移动到新内存。
    • 步骤3:释放原内存。
  2. 扩容的性能开销 :拷贝元素+内存分配/释放,因此如果提前知道元素数量,用reserve(n)预留容量可以避免频繁扩容,提升性能。

五、易混淆的resizereserve(结合size/capacity)

这两个函数是操作sizecapacity的核心,很多人容易搞混,这里总结对比:

函数 作用对象 size的影响 capacity的影响
resize(n) size 直接设置sizen n>原capacity,则capacity扩容到≥n;否则不变
reserve(n) capacity 无影响(size保持不变) n>原capacity,则capacity变为n;否则不变

举例说明

  • vector<int> arr; arr.resize(5);size=5capacity≥5(可直接下标赋值arr[0]=1)。
  • vector<int> arr; arr.reserve(5);size=0capacity=5不能 下标赋值arr[0]=1,因为size=0,元素不存在)。

六、总结关键点

  1. size实际元素个数capacity内存能容纳的最大元素个数 ,且capacity ≥ size
  2. 改变元素数量的操作(如push_backresize)影响size;只有内存重新分配时(如reserve、扩容)才影响capacity
  3. 扩容会带来性能开销,因此已知元素数量时,优先用reserve(n)预留容量,或直接用构造函数/resize设置size
  4. pop_back/erase不会释放内存(capacity不变),若要释放多余内存,可使用shrink_to_fit()(C++11+)。
相关推荐
郝学胜-神的一滴8 小时前
Qt实现圆角窗口的两种方案详解
开发语言·c++·qt·程序人生
散峰而望8 小时前
【算法竞赛】链表和 list
数据结构·c++·算法·链表·list·哈希算法·推荐算法
郝学胜-神的一滴9 小时前
Qt OpenGL 生成Mipmap技术详解
开发语言·c++·qt·系统架构·游戏引擎·图形渲染·unreal engine
w-w0w-w9 小时前
C++中vector的操作和简单实现
开发语言·数据结构·c++
Larry_Yanan9 小时前
Qt安卓开发(一)Qt6.10环境配置
android·开发语言·c++·qt·学习·ui
橘颂TA9 小时前
【剑斩OFFER】算法的暴力美学——力扣 227 题:基本计算机Ⅱ
c++·算法·leetcode·职场和发展·结构于算法
Z1Jxxx9 小时前
整除整除整除
开发语言·c++·算法
dlpay9 小时前
Visual Studio 2022中使用websocketpp
c++·ide·visual studio·boost·websocketpp
云雾J视界9 小时前
从Boost的设计哲学到工业实践:解锁下一代AI中间件架构的密码
c++·人工智能·中间件·架构·stackoverflow·boost