好的!既然你提到了 C++ 标准库中的容器类 <vector>
,我将为你详细讲解它的用法,包括基本概念、特性、功能以及实用示例。<vector>
是 C++ STL 中最常用的动态数组容器,适合需要动态调整大小的场景。它提供了灵活性和丰富的接口,是编程中不可或缺的工具。以下是完整的内容,适合学习和实践。
C++ 标准库:<vector>
<vector>
是一个模板类,表示动态大小的数组。它的主要特点是:
- 动态大小:可以在运行时添加或删除元素。
- 连续内存:元素存储在连续的内存块中,访问效率高。
- STL 兼容:支持迭代器、算法和丰富的成员函数。
- 自动管理内存:无需手动分配或释放内存。
包含头文件
#include <vector>
#include <iostream> // 通常配合使用
定义格式
std::vector<类型> 变量名;
类型
:元素的数据类型(如int
、double
、std::string
)。- 可选:初始大小或初始化列表。
基本用法
1. 声明和初始化
#include <vector>
#include <iostream>
int main() {
std::vector<int> vec1; // 空向量
std::vector<int> vec2(5, 10); // 5 个元素,每个值为 10
std::vector<int> vec3 = {1, 2, 3, 4}; // 初始化列表(C++11 起)
std::cout << "vec3: ";
for (int val : vec3) {
std::cout << val << " ";
}
std::cout << std::endl; // 输出:1 2 3 4
return 0;
}
2. 添加和删除元素
#include <vector>
#include <iostream>
int main() {
std::vector<int> vec;
vec.push_back(10); // 在末尾添加元素
vec.push_back(20);
vec.push_back(30);
std::cout << "Original: ";
for (int val : vec) {
std::cout << val << " "; // 输出:10 20 30
}
std::cout << std::endl;
vec.pop_back(); // 删除最后一个元素
std::cout << "After pop: ";
for (int val : vec) {
std::cout << val << " "; // 输出:10 20
}
std::cout << std::endl;
return 0;
}
push_back()
:O(1) 均摊复杂度,但可能触发内存重新分配。pop_back()
:O(1) 复杂度。
3. 访问元素
#include <vector>
#include <iostream>
int main() {
std::vector<double> vec = {1.5, 2.7, 3.9};
std::cout << "First: " << vec[0] << std::endl; // 下标访问
std::cout << "Second: " << vec.at(1) << std::endl; // 边界检查访问
std::cout << "Front: " << vec.front() << std::endl; // 第一个元素
std::cout << "Back: " << vec.back() << std::endl; // 最后一个元素
return 0;
}
输出:
First: 1.5
Second: 2.7
Front: 1.5
Back: 3.9
[]
:无边界检查,性能更高。at()
:有边界检查,超界抛出std::out_of_range
。
4. 大小和容量
#include <vector>
#include <iostream>
int main() {
std::vector<int> vec = {1, 2, 3};
std::cout << "Size: " << vec.size() << std::endl; // 当前元素数:3
std::cout << "Capacity: " << vec.capacity() << std::endl; // 当前容量:3 或更大
std::cout << "Empty? " << (vec.empty() ? "Yes" : "No") << std::endl; // 是否为空:No
vec.push_back(4);
std::cout << "After push - Size: " << vec.size() << ", Capacity: " << vec.capacity() << std::endl;
return 0;
}
size()
:当前元素个数。capacity()
:当前分配的内存可容纳的元素数(可能大于size()
)。- 容量不足时,
vector
会重新分配内存,通常翻倍增长。
5. 修改和调整
#include <vector>
#include <iostream>
int main() {
std::vector<int> vec = {1, 2, 3, 4};
vec.insert(vec.begin() + 1, 99); // 在第 2 个位置插入 99
std::cout << "After insert: ";
for (int val : vec) {
std::cout << val << " "; // 输出:1 99 2 3 4
}
std::cout << std::endl;
vec.erase(vec.begin()); // 删除第一个元素
std::cout << "After erase: ";
for (int val : vec) {
std::cout << val << " "; // 输出:99 2 3 4
}
std::cout << std::endl;
vec.resize(2); // 调整大小为 2
std::cout << "After resize: ";
for (int val : vec) {
std::cout << val << " "; // 输出:99 2
}
std::cout << std::endl;
return 0;
}
insert()
:O(n) 复杂度(移动后续元素)。erase()
:O(n) 复杂度。resize()
:若缩小则截断,若扩大则填充默认值。
6. 迭代器
#include <vector>
#include <iostream>
int main() {
std::vector<std::string> vec = {"Apple", "Banana", "Orange"};
for (auto it = vec.begin(); it != vec.end(); ++it) {
std::cout << *it << " ";
}
std::cout << std::endl; // 输出:Apple Banana Orange
return 0;
}
- 支持
begin()
、end()
、rbegin()
(逆向)、rend()
。
与 <array>
的对比
特性 | std::vector | std::array |
---|---|---|
大小 | 动态调整 | 编译时固定 |
内存管理 | 自动,动态分配 | 无额外分配 |
性能 | 可能有重新分配开销 | 无开销,接近 C 数组 |
STL 接口 | 丰富(插入、删除等) | 基础接口 |
注意事项
- 内存重新分配:
push_back()
可能导致容量翻倍,旧迭代器失效。 - 异常安全:
at()
抛异常,[]
不安全。 - 性能优化:用
reserve(n)
预分配容量,避免频繁重新分配。 - 清空:
clear()
清空元素,但不释放容量;shrink_to_fit()
可减少多余容量(C++11)。
小练习
以下是一个基于 <vector>
的练习题,你可以尝试:
问题:
写一个 C++ 程序:
- 定义一个
std::vector<int>
,初始化为 {1, 2, 3, 4, 5}。 - 在第 3 个位置插入 99。
- 删除第 1 个元素。
- 输出所有元素和当前大小。
参考答案(你可以先尝试)
#include <vector>
#include <iostream>
int main() {
std::vector<int> vec = {1, 2, 3, 4, 5};
// 插入 99 到第 3 个位置(索引 2)
vec.insert(vec.begin() + 2, 99);
// 删除第 1 个元素(索引 0)
vec.erase(vec.begin());
// 输出所有元素和大小
std::cout << "Elements: ";
for (int val : vec) {
std::cout << val << " ";
}
std::cout << "\nSize: " << vec.size() << std::endl;
return 0;
}
输出:
Elements: 2 3 99 4 5
Size: 5
下一步
- 如果你想试试这个练习,请写下你的代码,我会帮你检查。
- 如果你想要更复杂的内容(比如多维
vector
、排序、查找),或者设计<vector>
的测验题,请告诉我! - 你也可以提出具体问题,比如“如何用
<vector>
实现堆栈?”或“<vector>
的内存管理细节?”。
现在,你想做什么?试试练习,还是有其他需求?
发表回复