std::vector
是 C++ 标准模板库(STL)中的一个动态数组容器。它提供了动态大小调整和高效的随机访问功能,非常适合需要频繁插入、删除和访问元素的场景。std::vector
是在 <vector>
头文件中定义的,并且位于 std 命名空间中。
1. 特点
(1)动态大小调整:std::vector 可以根据需要自动调整其大小。
(2)连续内存存储:std::vector 内部使用连续内存存储元素,这意味着可以通过指针或索引高效地访问元素。
(3)高效的随机访问:支持常数时间的随机访问。
(4)自动管理内存:std::vector 自动管理其内部使用的内存,不需要手动分配和释放。
(5)支持常见容器操作:如插入、删除、遍历等。
2. 常用成员函数
2.1 迭代器
- begin():返回指向第一个元素的迭代器。
- end():返回指向最后一个元素之后的迭代器。
- rbegin():返回指向最后一个元素的逆向迭代器。
- rend():返回指向第一个元素之前的逆向迭代器。
2.2 容量
- size():返回当前元素的数量。
- capacity():返回当前分配的存储容量。
- empty():检查容器是否为空。
- reserve(size_type new_cap):请求分配至少能容纳 new_cap 个元素的存储空间。
- shrink_to_fit():请求减少容量以适应当前大小。
2.3 元素访问
- operator[]:访问指定位置的元素。
- at(size_type pos):访问指定位置的元素,并进行越界检查。
- front():访问第一个元素。
- back():访问最后一个元素。
- data():返回指向底层数组的指针。
2.4 修改器
- push_back(const T& value):在末尾添加元素。
- pop_back():删除末尾的元素。
- insert(iterator pos, const T& value):在指定位置插入元素。
- erase(iterator pos):删除指定位置的元素。
- clear():清空所有元素。
- resize(size_type count, T value = T()):调整容器大小。
示例代码
#include <iostream>
#include <vector>
int main() {
// 创建一个空的 vector
std::vector<int> vec;
// 添加元素
vec.push_back(10);
vec.push_back(20);
vec.push_back(30);
// 访问元素
std::cout << "First element: " << vec[0] << std::endl;
std::cout << "Second element: " << vec.at(1) << std::endl;
std::cout << "Last element: " << vec.back() << std::endl;
// 遍历元素
std::cout << "Elements: ";
for (const int& elem : vec) {
std::cout << elem << " ";
}
std::cout << std::endl;
// 在第二个位置插入值为15的元素
vec.insert(vec.begin() + 1, 15);
// 删除第三个元素
vec.erase(vec.begin() + 2);
// 重新遍历
std::cout << "Modified elements: ";
for (const int& elem : vec) {
std::cout << elem << " ";
}
std::cout << std::endl;
// 调整大小,并将扩展的元素初始化为100
vec.resize(5, 100);
// 重新遍历
std::cout << "Resized elements: ";
for (const int& elem : vec) {
std::cout << elem << " ";
}
std::cout << std::endl;
return 0;
}
3. 常见优化策略
在使用 std::vector
时,有一些常见的优化策略可以帮助你提高性能和效率。以下是一些优化建议:
3.1 预分配内存
使用 reserve 方法预分配内存可以减少内存重新分配的次数,从而提高性能。特别是在知道大概需要多少元素时,这非常有用。
#include <vector>
int main() {
std::vector<int> vec;
vec.reserve(1000); // 预分配足够的内存
for (int i = 0; i < 1000; ++i) {
vec.push_back(i);
}
return 0;
}
3.2 避免不必要的拷贝
在传递 std::vector
时,尽量使用引用(const 引用)来避免不必要的拷贝。
#include <vector>
// 使用 const 引用来避免拷贝
void processVector(const std::vector<int>& vec) {
// 处理 vector
}
int main() {
std::vector<int> vec = {1, 2, 3, 4, 5};
processVector(vec);
return 0;
}
3.3 使用 emplace_back 而不是 push_back
emplace_back
可以直接在容器内构造元素,避免了额外的拷贝或移动操作。
#include <vector>
struct MyStruct {
int x;
MyStruct(int val) : x(val) {}
};
int main() {
std::vector<MyStruct> vec;
vec.reserve(10); // 预分配内存
vec.emplace_back(1); // 直接在容器内构造元素
vec.emplace_back(2);
return 0;
}
3.4 使用 shrink_to_fit 释放多余内存
在删除大量元素后,可以使用 shrink_to_fit 来释放多余的内存。
#include <vector>
int main() {
std::vector<int> vec(1000, 1);
vec.erase(vec.begin(), vec.end() - 500); // 删除前 500 个元素
vec.shrink_to_fit(); // 释放多余的内存
return 0;
}
3.5 避免频繁的插入和删除操作
尽量避免在 std::vector
中间进行频繁的插入和删除操作,因为这会导致大量的元素移动。可以考虑使用其他适合频繁插入和删除的容器,如 std::list
或 std::deque
。
3.6 使用合适的迭代器
使用迭代器来遍历 std::vector
,避免使用索引访问,尤其是在大型 vector 中,这样可以提高代码的可读性和性能。
#include <vector>
#include <iostream>
int main() {
std::vector<int> vec = {1, 2, 3, 4, 5};
// 使用迭代器遍历 vector
for (auto it = vec.begin(); it != vec.end(); ++it) {
std::cout << *it << " ";
}
std::cout << std::endl;
return 0;
}
3.7 使用算法库
使用标准库中的算法,如 std::sort
、std::find
等,可以提高代码的效率和可读性。
#include <vector>
#include <algorithm>
#include <iostream>
int main() {
std::vector<int> vec = {5, 3, 1, 4, 2};
std::sort(vec.begin(), vec.end()); // 使用标准库算法排序
for (const int& elem : vec) {
std::cout << elem << " ";
}
std::cout << std::endl;
return 0;
}
3.8 避免多次调用 size() 函数
在循环中多次调用 size() 函数可能会影响性能,尤其是在一些复杂的容器中。可以将 size() 的结果存储在一个变量中,然后在循环中使用这个变量。
#include <vector>
#include <iostream>
int main() {
std::vector<int> vec = {1, 2, 3, 4, 5};
size_t size = vec.size(); // 将 size() 的结果存储在变量中
for (size_t i = 0; i < size; ++i) {
std::cout << vec[i] << " ";
}
std::cout << std::endl;
return 0;
}
总结
std::vector
是一个强大且灵活的容器,适用于需要动态调整大小、频繁插入和删除操作的场景。它提供了丰富的成员函数和操作,能够满足大多数常见的使用需求。通过理解和掌握 std::vector
,可以大大提高 C++ 编程的效率和代码的可读性。