C++动态数组:std::vector一维与二维的初始化和操作指南
在C++中,std::vector 是一个非常强大的容器,可以动态地管理数组的大小,并且提供了许多方便的操作。相比于传统的数组,std::vector 更加灵活和安全。本文将介绍如何初始化一维和二维的 std::vector 数组,并展示一些常见的用法。
1. 一维 std::vector 的初始化
1.1 默认初始化
默认情况下,std::vector 会被初始化为空。
#include <vector>
using namespace std;
int main() {
vector<int> vec; // 默认初始化,vec为空
return 0;
}
1.2 指定大小初始化
可以指定 std::vector 的大小,所有元素会被默认初始化为 0(对于基本类型)。
vector<int> vec(10); // 初始化大小为 10,所有元素为 0
1.3 指定大小和初始值
可以在初始化时指定大小和初始值。
vector<int> vec(10, 5); // 初始化大小为 10,所有元素为 5
1.4 使用列表初始化
可以使用花括号 {} 进行列表初始化。
vector<int> vec = {1, 2, 3, 4, 5}; // 初始化包含 5 个元素
1.5 从数组初始化
可以从一个已有的数组初始化 std::vector。
int arr[] = {1, 2, 3, 4, 5};
vector<int> vec(arr, arr + 5); // 使用数组初始化
2. 二维 std::vector 的初始化
二维 std::vector 实际上是一个 std::vector 的 std::vector,即 vector<vector<T>>。
2.1 默认初始化
默认情况下,二维 std::vector 为空。
vector<vector<int>> matrix; // 默认初始化,matrix为空
2.2 指定大小初始化
可以指定行数和列数,所有元素会被默认初始化为 0。
int rows = 3, cols = 4;
vector<vector<int>> matrix(rows, vector<int>(cols)); // 3 行 4 列,所有元素为 0
2.3 指定大小和初始值
可以在初始化时指定大小和初始值。
int rows = 3, cols = 4;
vector<vector<int>> matrix(rows, vector<int>(cols, 5)); // 3 行 4 列,所有元素为 5
2.4 使用列表初始化
可以使用嵌套的花括号 {} 进行列表初始化。
vector<vector<int>> matrix = {
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
}; // 初始化一个 3x3 的二维数组
2.5 动态添加行和列
可以通过 push_back 动态添加行和列。
vector<vector<int>> matrix;
for (int i = 0; i < 3; ++i) {
vector<int> row = {i, i + 1, i + 2};
matrix.push_back(row); // 动态添加行
}
3. 初始化 bool 类型的 std::vector
std::vector<bool> 是一个特化的版本,它的存储方式与普通 std::vector 不同,每个 bool 值只占用 1 个比特。
3.1 默认初始化
vector<bool> vec; // 默认初始化,vec为空
3.2 指定大小初始化
vector<bool> vec(10); // 初始化大小为 10,所有元素为 false
3.3 指定大小和初始值
vector<bool> vec(10, true); // 初始化大小为 10,所有元素为 true
3.4 使用列表初始化
vector<bool> vec = {true, false, true, false}; // 初始化包含 4 个元素
3.5 示例代码
以下是一个完整的示例,展示如何初始化一维和二维的 std::vector,并输出它们的内容。
#include <iostream>
#include <vector>
using namespace std;
int main() {
// 一维 vector 初始化
vector<int> vec1 = {1, 2, 3, 4, 5};
cout << "一维 vector: ";
for (int val : vec1) {
cout << val << " ";
}
cout << endl;
// 二维 vector 初始化
vector<vector<int>> matrix = {
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
};
cout << "二维 vector:" << endl;
for (const auto& row : matrix) {
for (int val : row) {
cout << val << " ";
}
cout << endl;
}
// bool vector 初始化
vector<bool> boolVec = {true, false, true, false};
cout << "bool vector: ";
for (bool val : boolVec) {
cout << val << " ";
}
cout << endl;
return 0;
}
在使用 std::vector 时,开发者可能会遇到一些常见问题,比如数组溢出、如何高效地添加数据、何时使用 push_back 和 insert 等。本文接下来将详细探讨这些问题,并提供解决方案和最佳实践。
4. 常见问题
4.1 数组溢出
std::vector 是动态数组,它会自动管理内存,因此不会像普通数组那样发生“数组溢出”问题。但是,如果访问超出当前 vector 范围的元素(例如使用 operator[] 或 at()),可能会导致未定义行为或抛出异常。
示例:
vector<int> vec = {1, 2, 3};
cout << vec[3]; // 未定义行为,vec 只有 3 个元素
cout << vec.at(3); // 抛出 std::out_of_range 异常
解决方法:
- 使用
at()方法访问元素,它会进行边界检查并抛出异常。 - 在访问元素之前,检查
vector的大小:if (index < vec.size()) { cout << vec[index]; }
4.2 如何添加数据
std::vector 提供了多种添加数据的方法,最常用的是 push_back 和 insert。
push_back
- 作用:在
vector的末尾添加一个元素。 - 时间复杂度:平均 O(1),最坏情况下 O(n)(当需要重新分配内存时)。
- 适用场景:在
vector末尾添加单个元素。
示例:
vector<int> vec = {1, 2, 3};
vec.push_back(4); // vec 变为 {1, 2, 3, 4}
insert
- 作用:在指定位置插入一个或多个元素。
- 时间复杂度:O(n),因为需要移动插入点之后的元素。
- 适用场景:在
vector的任意位置插入元素。
示例:
vector<int> vec = {1, 2, 3};
vec.insert(vec.begin() + 1, 4); // vec 变为 {1, 4, 2, 3}
4.3 何时使用 push_back,何时使用 insert
-
使用
push_back:- 当只需要在
vector的末尾添加元素时。 - 当不需要关心插入位置时。
- 当需要高效地添加大量元素时(因为
push_back的平均时间复杂度是 O(1))。
- 当只需要在
-
使用
insert:- 当需要在
vector的任意位置插入元素时。 - 当需要插入多个元素时(
insert支持插入一个范围内的元素)。 - 当需要精确控制元素的位置时。
- 当需要在
示例:
vector<int> vec = {1, 2, 3};
// 使用 push_back 添加元素
vec.push_back(4); // vec 变为 {1, 2, 3, 4}
// 使用 insert 在指定位置插入元素
vec.insert(vec.begin() + 1, 5); // vec 变为 {1, 5, 2, 3, 4}
5. 常见问题
5.1 如何高效地添加大量数据
如果需要一次性添加大量数据,可以使用 insert 或 assign 方法,而不是多次调用 push_back。
示例:
vector<int> vec = {1, 2, 3};
vector<int> newData = {4, 5, 6};
// 使用 insert 添加多个元素
vec.insert(vec.end(), newData.begin(), newData.end()); // vec 变为 {1, 2, 3, 4, 5, 6}
// 使用 assign 替换所有元素
vec.assign(newData.begin(), newData.end()); // vec 变为 {4, 5, 6}
5.2 如何避免频繁的内存重新分配
std::vector 在添加元素时,如果当前容量不足,会自动重新分配内存并复制所有元素。为了避免频繁的内存重新分配,可以使用 reserve 方法预先分配足够的空间。
示例:
vector<int> vec;
vec.reserve(100); // 预先分配 100 个元素的空间
for (int i = 0; i < 100; ++i) {
vec.push_back(i); // 不会触发内存重新分配
}
5.3 如何清空 vector
可以使用 clear 方法清空 vector,但不会释放内存。如果需要释放内存,可以使用 swap 技巧。
示例:
vector<int> vec = {1, 2, 3};
vec.clear(); // 清空元素,但保留内存
// 释放内存
vector<int>().swap(vec); // 清空并释放内存
5.4 如何高效地删除元素
std::vector 提供了 erase 方法用于删除元素,但删除元素会导致后续元素的移动,因此时间复杂度为 O(n)。
示例:
vector<int> vec = {1, 2, 3, 4, 5};
vec.erase(vec.begin() + 2); // 删除第 3 个元素,vec 变为 {1, 2, 4, 5}
如果需要高效地删除多个元素,可以使用“移除-擦除”惯用法(Erase-Remove Idiom)。
示例:
vector<int> vec = {1, 2, 3, 4, 5};
vec.erase(remove(vec.begin(), vec.end(), 3), vec.end()); // 删除所有值为 3 的元素
5. 总结
- 一维
std::vector:可以通过默认初始化、指定大小、指定初始值、列表初始化等方式进行初始化。 - 二维
std::vector:实际上是vector<vector<T>>,可以通过嵌套的vector进行初始化。 std::vector<bool>:是一个特化的版本,每个元素只占用 1 个比特,初始化方式与其他std::vector类似。- 数组溢出:使用
at()或检查边界来避免。 - 添加数据:
- 使用
push_back在末尾添加元素。 - 使用
insert在任意位置插入元素。
- 使用
- 高效操作:
- 使用
reserve避免频繁内存重新分配。 - 使用“移除-擦除”惯用法高效删除元素。
- 使用
- 清空
vector:使用clear或swap技巧。
std::vector 是 C++ 中非常强大的工具,能够动态管理数组的大小,并且提供了丰富的操作接口。掌握它的初始化方法对于编写高效、灵活的代码非常重要。
如果你有任何问题或建议,欢迎在评论区留言讨论!
更多推荐


所有评论(0)