std::vector 是 C++ 标准库中最常用的动态数组容器之一,它提供了灵活的内存管理能力,可以根据元素数量自动扩容。resize() 作为 vector 中的重要成员函数,经常用于调整容器大小,但很多开发者对它与 reserve()、push_back() 等方法之间的区别并不清楚。
理解 vector::resize() 的作用机制,不仅有助于编写更高效的 C++ 程序,也能避免因为误用导致的性能问题或逻辑错误。
一、vector::resize()基本作用
resize() 方法用于改变 std::vector 当前存储的元素数量,也就是修改 vector 的 size()。
函数原型如下:
C++void resize(size_type count); void resize(size_type count, const value_type& value);
其中:
-
count表示调整后的元素数量。 -
value表示当新增元素时,用于初始化新元素的默认值。
简单来说:
-
新大小大于当前 size:增加元素。
-
新大小小于当前 size:删除末尾元素。
-
新大小等于当前 size:不发生变化。
例如:
C++#include#include int main() { std::vector<int> nums = {1, 2, 3}; nums.resize(5); for (int n : nums) { std::cout << n << " "; } return 0; }
输出:
1 2 3 0 0
原 vector 有 3 个元素,调用 resize(5) 后增加两个 int 类型元素,由于 int 默认初始化为 0,因此新增位置保存为 0。
二、resize扩容时的实现原理
当调用:
C++vector.resize(newSize);
如果:
C++newSize > size()
vector 需要增加元素数量。
内部执行过程大致如下:
-
判断当前容量
capacity()是否足够。 -
如果容量足够,直接在已有内存空间中构造新元素。
-
如果容量不足,则重新申请更大的内存。
-
将旧元素移动或复制到新内存。
-
销毁旧内存。
-
更新 size。
例如:
C++std::vector<int> v = {10, 20, 30}; v.resize(6);
执行前:
size = 3 capacity >= 3
执行后:
size = 6 capacity >= 6
新增三个元素:
10 20 30 0 0 0
需要注意的是,resize() 改变的是元素数量,而不仅仅是分配空间。
三、resize与capacity的关系
很多 C++ 初学者容易混淆 size() 和 capacity()。
size()
表示当前 vector 中实际存在的元素数量:
C++std::vector<int> v = {1,2,3}; std::cout << v.size();
输出:
3
说明 vector 中有 3 个元素。
capacity()
表示 vector 当前已经分配的内存能够容纳多少元素:
C++std::cout << v.capacity();
可能输出:
4
也可能输出:
8
具体数值由编译器实现决定。
调用:
C++v.resize(100);
之后:
C++v.size();
一定变成:
100
但是:
C++v.capacity();
可能大于等于:
100
因此:
-
size 代表实际元素数量。
-
capacity 代表预留空间大小。
四、resize缩小时发生什么
当新的大小小于当前 size:
C++std::vector<int> v = {1,2,3,4,5}; v.resize(2);
执行后:
1 2
后三个元素会被销毁。
但是:
C++v.capacity();
通常不会减少。
例如:
C++std::cout << v.capacity();
可能仍然输出:
5
甚至更大。
原因是 vector 会保留已经申请的内存,以便未来继续添加元素,提高性能。
如果希望释放多余容量,可以使用:
C++v.shrink_to_fit();
例如:
C++v.resize(2); v.shrink_to_fit();
不过需要注意:
shrink_to_fit() 只是请求释放,不是强制要求,具体是否执行由标准库实现决定。
五、resize与reserve的区别
这是 C++ vector 使用中最容易混淆的问题之一。
reserve()
用于提前分配内存:
C++vector.reserve(n);
它只改变容量:
C++std::vector<int> v; v.reserve(100); std::cout << v.size();
输出:
0
因为没有创建任何元素。
resize()
用于改变元素数量:
C++v.resize(100);
执行后:
C++v.size();
结果:
100
同时创建 100 个元素。
对比:
| 方法 | 修改size | 修改capacity | 创建元素 |
|---|---|---|---|
| resize | 是 | 可能 | 是 |
| reserve | 否 | 是 | 否 |
使用场景:
提前知道元素数量:
C++std::vector<int> data; data.reserve(1000); for(int i = 0; i < 1000; i++) { data.push_back(i); }
适合使用 reserve()。
需要直接访问指定位置:
C++std::vector<int> data; data.resize(100); data[50] = 10;
适合使用 resize()。
六、resize新增元素的初始化规则
不同类型的元素,初始化方式不同。
基本类型
例如:
C++std::vector<int> v; v.resize(3);
结果:
0 0 0
也可以指定默认值:
C++v.resize(3, 100);
结果:
100 100 100
自定义类型
例如:
C++class Person { public: Person() { std::cout << "constructor"; } }; std::vector<Person> people; people.resize(5);
vector 会调用默认构造函数创建 5 个对象。
如果对象没有默认构造函数:
C++class Person { public: Person(int age){} };
那么:
C++people.resize(5);
会编译失败。
因为 resize 需要知道如何创建新增元素。
七、resize对迭代器和引用的影响
调用 resize 后,需要注意迭代器失效问题。
扩容导致失效
例如:
C++std::vector<int> v = {1,2,3}; auto it = v.begin(); v.resize(100);
如果发生重新分配:
-
原来的 iterator 失效。
-
原来的指针失效。
-
原来的引用失效。
原因是元素可能已经移动到新的内存地址。
缩小导致部分失效
例如:
C++std::vector<int> v = {1,2,3,4}; auto it = v.begin()+3; v.resize(2);
元素 4 被删除,因此:
C++it
已经失效。
但是前两个元素的引用通常仍然有效。
八、resize的时间复杂度分析
resize() 的复杂度取决于操作类型。
增加元素
如果无需重新分配:
时间复杂度:
O(n)
其中 n 是新增元素数量。
因为需要构造新的元素。
如果发生扩容:
时间复杂度:
O(size + n)
因为需要移动旧元素,同时创建新元素。
删除元素
缩小时:
O(size - newSize)
需要销毁被删除的对象。
对于 int 等简单类型,销毁成本非常低。
对于复杂对象:
C++vector<MyClass>
可能涉及析构函数调用。
九、resize常见使用场景
1. 提前创建固定大小数组
例如:
C++std::vector<int> buffer; buffer.resize(1024); buffer[0] = 100;
相比连续 push_back,更适合随机访问。
2. 修改二维数组大小
例如:
C++std::vector<std::vector<int>> matrix; matrix.resize(5); for(auto& row : matrix) { row.resize(5); }
创建:
5 × 5
二维结构。
3. 文件读取缓冲区
例如:
C++std::vector<char> buffer; buffer.resize(fileSize); read(buffer.data(), fileSize);
可以直接获取连续内存。
十、使用resize时的注意事项
1. 不要用resize代替reserve
错误方式:
C++vector<int> v; v.resize(1000); for(int i=0;i<1000;i++) { v.push_back(i); }
这样会产生:
1000个默认元素 + 1000个新增元素
最终 size:
2000
正确方式:
C++vector<int> v; v.reserve(1000); for(int i=0;i<1000;i++) { v.push_back(i); }
2. resize不会自动释放内存
很多开发者认为:
C++v.resize(0);
会释放所有内存。
实际上:
C++v.size()==0
但:
C++v.capacity()
可能仍然很大。
如果需要释放:
C++std::vector<int>().swap(v);
或者:
C++v.clear(); v.shrink_to_fit();
3. 大对象避免频繁resize
如果 vector 存储大型对象:
C++vector<BigObject>
频繁调整大小可能导致:
-
大量构造。
-
大量析构。
-
内存复制。
应提前规划容量。
十一、vector::resize源码逻辑简析
不同标准库实现略有差异,但核心流程类似:
C++void resize(size_type n) { if(n > size()) { insert(end(), n - size(), value_type()); } else if(n < size()) { erase(begin()+n, end()); } }
实际 STL 实现会进行更复杂的优化:
-
判断容量。
-
使用移动构造。
-
使用内存分配器。
-
进行异常安全处理。
现代 C++ 中通常优先使用移动语义:
C++T(T&& other);
减少对象复制,提高效率。
十二、总结
std::vector::resize() 是 C++ vector 中用于调整元素数量的重要方法,它不仅改变 size,还会根据情况创建或销毁对象。
核心要点如下:
-
resize()修改元素数量。 -
增大 size 会创建新元素。
-
减小 size 会删除尾部元素。
-
resize 可能触发内存重新分配。
-
resize 与 reserve 作用完全不同。
-
resize 后需要关注迭代器失效问题。
-
对大型对象使用时需要考虑性能影响。
掌握 vector::resize() 的内部机制,可以帮助开发者更加合理地管理动态数组,提高 C++ 程序运行效率和稳定性。