【std::vector】避免频繁扩容方法

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

文章目录


当你已知动态数组(vector)的大小 ,想要直接创建对应大小的空间并直接赋值(避免push_back带来的扩容或频繁追加操作),核心思路是先确定vectorsize(元素个数)或提前预留足够的capacity(容量),再通过下标/迭代器直接赋值。以下是几种最常用的方法,按场景分类说明:

一、核心场景:已知大小,需手动填充不同数据

这种场景是最常见的(比如已知数组大小为n,后续要通过循环赋值1、2、3...n),推荐两种方式:

方法1:创建时直接用构造函数指定大小

利用vector的构造函数vector<T>(n)直接创建包含n个默认初始化元素的vector,此时size = ncapacity ≥ n,可以直接通过**下标[] at()**赋值(无需push_back)。

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

int main() {
    // 已知数组大小为5,直接创建包含5个默认初始化元素(int为0)的vector
    int n = 5;
    vector<int> arr(n); // 此时arr: [0, 0, 0, 0, 0],size=5,capacity≥5

    // 直接通过下标赋值,不会触发任何内存扩容
    for (int i = 0; i < n; i++) {
        arr[i] = i + 1; // 赋值为1,2,3,4,5
        // 或用arr.at(i) = i + 1; // at()有越界检查,更安全(越界会抛异常),[]无检查(越界是未定义行为)
    }

    // 输出:1 2 3 4 5
    for (int num : arr) {
        cout << num << " ";
    }

    return 0;
}
方法2:先声明,再用resize()设置大小

如果需要先声明vector,再后续确定大小(比如大小由变量计算得到),可以用resize(n)vectorsize设置为n,效果和构造函数一致。

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

int main() {
    vector<int> arr; // 初始为空,size=0,capacity=0
    int n = 5;
    arr.resize(n); // 调整size为5,元素默认初始化(int为0),capacity≥5

    // 直接赋值
    for (int i = 0; i < n; i++) {
        arr[i] = i * 2; // 赋值为0,2,4,6,8
    }

    // 输出:0 2 4 6 8
    for (int num : arr) {
        cout << num << " ";
    }

    return 0;
}

二、进阶场景:已知大小且元素有统一初始值

如果不仅知道大小,还知道所有元素的初始值(比如大小为5,所有元素初始值为10),可以直接用带初始值的构造函数,一步完成大小和值的初始化,无需后续赋值。

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

int main() {
    int n = 5;
    int init_val = 10;
    // 创建包含5个元素的vector,每个元素都是10
    vector<int> arr(n, init_val); // 此时arr: [10, 10, 10, 10, 10]

    // 若需要修改部分元素,仍可直接下标赋值
    arr[2] = 99; // arr变为:[10,10,99,10,10]

    // 输出:10 10 99 10 10
    for (int num : arr) {
        cout << num << " ";
    }

    return 0;
}

三、特殊场景:已知大小,且知道具体元素列表(C++11+)

如果不仅知道大小,还知道每个元素的具体值,可以用初始化列表 直接创建,此时vector的大小就是元素列表的长度,无需额外设置。

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

int main() {
    // 已知元素为1,3,5,7,9(大小为5),直接用初始化列表创建
    vector<int> arr{1, 3, 5, 7, 9};

    // 也可修改元素
    arr[1] = 4; // arr变为:[1,4,5,7,9]

    // 输出:1 4 5 7 9
    for (int num : arr) {
        cout << num << " ";
    }

    return 0;
}

四、补充:若非要用push_back(但不想扩容)

如果你偶尔还是需要用push_back,但想避免扩容(因为扩容会涉及内存重新分配和元素拷贝),可以用**reserve(n)预留容量**(注意:reserve只改变capacity,不改变size,所以不能直接下标赋值)。

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

int main() {
    int n = 5;
    vector<int> arr;
    arr.reserve(n); // 预留5个元素的容量,size仍为0,不会触发扩容

    // 用push_back添加元素,此时不会扩容(因为容量足够)
    for (int i = 0; i < n; i++) {
        arr.push_back(i + 1);
    }

    // 输出:1 2 3 4 5
    for (int num : arr) {
        cout << num << " ";
    }

    return 0;
}

关键注意事项(避坑点)

  1. 区分resizereserve
    • resize(n):修改vector的**size**(元素个数),会创建/删除元素,因此可以直接下标赋值。
    • reserve(n):仅预留**capacity**(内存容量),不改变size,因此不能直接下标赋值(此时size=0,下标访问会越界)。
  2. 下标[]at()的区别
    • arr[i]:无越界检查,效率高,但越界时会导致未定义行为(程序崩溃)。
    • arr.at(i):有越界检查,越界时会抛出out_of_range异常,更安全,适合调试。
相关推荐
郝学胜-神的一滴8 小时前
Qt实现圆角窗口的两种方案详解
开发语言·c++·qt·程序人生
CSDN_RTKLIB8 小时前
【std::vector】size、capacity小结
c++·stl
散峰而望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