在C++中,std::vector是最常用的容器之一,它提供了动态数组的功能。vector类有两个常用但经常被误解的成员函数:resize()和reserve()。理解这两个函数的区别和正确使用方法,可以显著提升你的程序性能。让我们深入探讨这两个函数的特性和用法。
- resize() 函数
作用:
- 改变vector中元素的数量
- 如果新尺寸大于当前尺寸,会在末尾添加新元素
- 如果新尺寸小于当前尺寸,会删除末尾的元素
语法:
void resize(size_type new_size);
void resize(size_type new_size, const value_type& value);
特点:
- 会改变vector的size()
- 可能会改变vector的capacity()
- 如果指定了value参数,新添加的元素会被初始化为这个值
示例:
std::vector<int> v = {1, 2, 3};
v.resize(5); // v becomes {1, 2, 3, 0, 0}
v.resize(2); // v becomes {1, 2}
v.resize(4, 10); // v becomes {1, 2, 10, 10}
- reserve() 函数
作用:
- 预分配内存空间,但不创建任何元素
- 增加vector的capacity,但不改变它的size
语法:
void reserve(size_type new_cap);
特点:
- 只改变vector的capacity(),不改变size()
- 如果new_cap大于当前capacity,会重新分配内存
- 如果new_cap小于或等于当前capacity,函数不做任何事
示例:
std::vector<int> v;
v.reserve(10); // capacity becomes 10, size is still 0
v.push_back(1); // size becomes 1, capacity is still 10
关键区别:
-
对元素的影响
- resize()会实际创建或销毁元素
- reserve()不创建任何元素,只预分配内存
-
对size()的影响
- resize()改变size()
- reserve()不改变size()
-
对capacity()的影响
- resize()可能改变capacity()
- reserve()只增加capacity(),不减少
-
性能影响
- resize()可能涉及元素的构造或析构,可能较慢
- reserve()只涉及内存分配,通常较快
-
使用场景
- resize()用于实际需要特定数量元素时
- reserve()用于提前知道大概需要多少元素,想要避免多次重新分配内存时
性能优化示例:
不使用reserve():
std::vector<int> v;
for (int i = 0; i < 10000; ++i) {
v.push_back(i); // 可能导致多次内存重新分配
}
使用reserve():
std::vector<int> v;
v.reserve(10000); // 一次性分配足够的内存
for (int i = 0; i < 10000; ++i) {
v.push_back(i); // 不会导致内存重新分配
}
在这个例子中,使用reserve()可以显著提高性能,因为它避免了多次内存重新分配。
深入理解:
-
内存重分配
当vector的size超过其capacity时,会发生内存重分配。这个过程涉及:- 分配新的更大的内存块
- 将所有元素复制或移动到新内存
- 释放旧内存
这是一个耗时的操作,特别是对于大型vector。
-
增长策略
不同的C++标准库实现可能有不同的vector增长策略。常见的策略是每次增长将capacity翻倍,这样可以平摊重分配的成本。 -
内存使用
reserve()可以帮助减少内存碎片,因为它允许一次性分配大块内存,而不是多次小额分配。 -
异常安全
resize()可能会抛出异常(如果元素的构造函数抛出异常),而reserve()通常不会(除非内存分配失败)。
实际应用示例:
- 高效地构建大型vector:
std::vector<MyClass> objects;
objects.reserve(1000000); // 预分配内存,避免频繁重分配
for (int i = 0; i < 1000000; ++i) {
objects.emplace_back(/* 构造参数 */); // 使用emplace_back直接在vector中构造对象
}
- 使用resize()初始化vector:
std::vector<int> data;
data.resize(100, 42); // 创建100个元素,所有元素值为42
结论:
正确理解和使用resize()和reserve()可以显著提高你的程序性能。resize()用于改变vector中实际元素的数量,而reserve()用于优化内存分配。在你知道vector大概需要多少元素时,使用reserve()可以避免不必要的内存重分配,从而提高性能。
记住,优化是一门平衡的艺术。过度使用reserve()可能会导致内存浪费,而不使用它则可能导致性能下降。理解你的数据结构和算法需求,根据实际情况做出明智的选择。