在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::vectorstd::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_backinsert 等。本文接下来将详细探讨这些问题,并提供解决方案和最佳实践。


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_backinsert

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 如何高效地添加大量数据

如果需要一次性添加大量数据,可以使用 insertassign 方法,而不是多次调用 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:使用 clearswap 技巧。

std::vector 是 C++ 中非常强大的工具,能够动态管理数组的大小,并且提供了丰富的操作接口。掌握它的初始化方法对于编写高效、灵活的代码非常重要。

如果你有任何问题或建议,欢迎在评论区留言讨论!
在这里插入图片描述

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐