向 vector 对象中添加元素(三十九)

1. 向空 vector 中添加元素

1.1 使用 push_back 添加元素

如果在 vector 定义时还不知道所需的元素个数,可以先创建一个空 vector,然后利用成员函数 push_back 将元素依次“压入” vector 的尾部。push_back 函数将传入的值作为新元素添加到 vector 的末尾,内部会根据需要动态调整存储容量。

例如,下面的代码依次将整数 0~99 添加到一个空的 vector 中:

#include <iostream>
#include <vector>
using std::vector;
using std::cout;
using std::endl;

int main() {
    
    
    vector<int> v2;  // 创建一个空 vector<int>
    for (int i = 0; i < 100; ++i) {
    
    
        v2.push_back(i);  // 将整数 i 添加到 vector 的尾端
    }
    // 循环结束后,v2 有 100 个元素,依次为 0 到 99
    cout << "v2 size: " << v2.size() << endl;
    return 0;
}

1.2 从标准输入读取元素并添加到 vector

在实际应用中,我们经常需要从用户或文件中动态读取数据,然后存储到 vector 中。例如,下面的代码从标准输入中读取一个个单词,并将其依次添加到 vector 中:

#include <iostream>
#include <string>
#include <vector>
using std::cin;
using std::cout;
using std::endl;
using std::string;
using std::vector;

int main() {
    
    
    string word;
    vector<string> text;  // 创建一个空 vector<string>
    
    // 循环读取单词,直到遇到文件结束或非法输入
    while (cin >> word) {
    
    
        text.push_back(word);  // 将读取到的单词添加到 vector 中
    }
    
    // 输出所有读取的单词,每个单词占一行
    for (const auto &w : text) {
    
    
        cout << w << endl;
    }
    
    return 0;
}

在这个例子中,我们先创建了一个空 vector,然后利用 while 循环不断从标准输入读取单词,调用 push_back 将每个单词依次存入 vector。注意,while 循环使用 cin >> word 作为条件,会在读取失败时终止循环。

2. 使用 push_back 的编程假定与注意事项

虽然向 vector 中添加元素十分方便,但这种操作也蕴含了一些编程假定,程序员需要格外注意:

2.1 循环条件与 vector 尺寸

当循环体内包含向 vector 添加元素(如 push_back)的操作时,不能使用范围 for 循环来遍历 vector,因为范围 for 循环要求在遍历过程中不改变容器的大小。如果在循环过程中 vector 的容量发生变化,可能会导致未定义行为或逻辑错误。

错误示例:

#include <iostream>
#include <vector>
using std::vector;
using std::cout;
using std::endl;

int main() {
    
    
    vector<int> v{
    
    1, 2, 3};
    // 错误:在范围 for 循环中添加元素会改变容器大小
    for (auto x : v) {
    
    
        cout << x << " ";
        v.push_back(x);  // 不允许在遍历过程中修改容器大小
    }
    return 0;
}

因此,如果循环体需要添加新元素,应使用普通的 while 或 for 循环,并确保循环条件正确控制。

2.2 循环结束条件

在动态添加元素的循环中,要明确循环的结束条件。如果结束条件依赖于 vector 的大小,而大小又在循环中不断变化,可能导致死循环或者访问越界。因此,设计循环时应仔细考虑条件表达式,确保不会错误访问容器。

例如,在以下场景中,如果输入数据数量未知,建议将添加元素和遍历操作分离进行,而不要在同一个循环中混用读取和遍历操作。

3. 总结

  • 动态添加元素:

    • 如果事先不知道 vector 的确切大小,可先创建一个空 vector,然后利用 push_back 在运行时逐步添加元素。
  • 从输入读取数据:

    • 结合 while 循环和 push_back,可以动态读取用户或文件数据,并将其存入 vector 中。
  • 注意循环控制:

    • 在循环中添加元素时不要使用范围 for 循环,因为这会改变容器大小;应使用普通 for 或 while 循环,并确保循环条件正确。
  • 性能与安全:

    • 虽然 vector 的动态添加非常高效,但程序员需要确保循环逻辑正确,避免因 vector 尺寸变化导致未定义行为。

通过正确使用 push_back 和设计合适的循环条件,可以灵活高效地构建 vector 对象,使代码适应运行时数据量的变化,并避免因容器尺寸变化而引起的问题。

参考资料

  • cppreference.com 中关于 std::vector 的详细说明
  • 各大 C++ 编码规范(如 Google C++ Style Guide)中对容器操作的建议

这篇全面讲解希望能帮助你深入理解如何向 vector 对象中添加元素,以及在动态数据处理过程中应注意的关键细节。