C++ vector 添加元素

在 C++ 中,创建好 vector 容器之后,很多时候数据是在运行过程中逐步产生的,需要我们随时往容器中添加新元素。向 vector 添加元素常用的有以下 3 个成员函数:

  • push_back():在容器末尾追加一个元素,日常开发最常用。
  • emplace_back():在容器末尾直接生成并添加一个元素。
  • insert():在指定位置插入一个或多个元素。

在实际开发中,绝大多数添加操作都发生在容器末尾。对于初学的小伙伴来说,先把 push_back() 掌握好,平时写代码时的大部分需求就已经够用了。

在末尾添加元素

往 vector 的末尾追加新元素时,前面已有的元素不需要挪动位置,因此执行速度最快,用法也最简单。常用的有 push_back() 和 emplace_back() 这两个函数。

1. push_back() 函数

从英文意思上很容易记住,push_back 就是 “往末尾推入” 的意思,它的作用是把一个新元素添加到当前容器的最后面。

语法:

容器名.push_back(元素值);

说明:

每调用一次 push_back(),新元素就会排到当前所有元素的末尾,同时容器的元素数量 size() 会自动加 1。和普通数组一样,vector 也可以直接配合范围 for 循环依次把里面的元素打印出来。

示例 1:使用 push_back() 追加元素

#include <iostream>
#include <vector>

int main() {
    std::vector<int> prices = {15, 25};

    prices.push_back(35);    // 在末尾添加 35
    prices.push_back(45);    // 在末尾添加 45

    std::cout << "元素数量:" << prices.size() << '\n';
    for (int price : prices) {
        std::cout << price << ' ';
    }
    std::cout << '\n';
    return 0;
}

运行结果如下。

元素数量:4
15 25 35 45

分析:

在这个例子中,prices 一开始只有 15 和 25 两个元素。当我们第 1 次调用 prices.push_back(35); 时,35 会追加到 25 的后面。第 2 次调用 prices.push_back(45); 时,45 又会追加到 35 的后面,最终元素总数变成 4。

在实际开发中,更常见的做法是先定义一个空的 vector,再配合 for 循环把运行过程中产生的数据逐个装进去。下面我们来看一个例子。

示例 2:配合循环动态添加元素

#include <iostream>
#include <vector>

int main() {
    std::vector<int> nums;

    for (int i = 1; i <= 5; i++) {
        nums.push_back(i * 10);    // 依次追加 10 到 50
    }

    for (int num : nums) {
        std::cout << num << ' ';
    }
    std::cout << '\n';
    return 0;
}

运行结果如下。

10 20 30 40 50

分析:

nums 刚定义出来时是空的。在循环过程中,i 从 1 变化到 5。每次循环都会算出 i * 10 并调用 push_back() 追加到容器末尾,容器的长度也就跟着一步步自动增长到了 5。

2. emplace_back() 函数(了解)

从 C++11 标准开始,vector 还提供了另一个在末尾添加元素的成员函数 emplace_back(),其中 emplace 是 “就地放置” 的意思。

语法:

容器名.emplace_back(元素值);

说明:

对于 int、double、std::string 等常见数据类型来说,emplace_back() 的写法和运行效果与 push_back() 完全一样,同样是在容器末尾追加一个新元素。

示例 3:使用 emplace_back() 添加元素

#include <iostream>
#include <string>
#include <vector>

int main() {
    std::vector<std::string> sites;
    sites.emplace_back("绿叶网");
    sites.emplace_back("www.lvyenet.com");

    std::cout << "元素数量:" << sites.size() << '\n';
    std::cout << sites[0] << ":" << sites[1] << '\n';
    return 0;
}

运行结果如下。

元素数量:2
绿叶网:www.lvyenet.com

分析:

在这个例子中,我们先定义了一个保存字符串的空容器 sites,随后连续调用两次 emplace_back() 向末尾追加了两个字符串。

既然运行效果一样,为什么 C++ 还要多提供一个 emplace_back() 呢?简单来说,push_back() 是先把数据准备好,再放进容器末尾。而 emplace_back() 则是直接在容器末尾的内存位置上把数据生成出来,省去了一次中间传递的步骤。

在初学阶段,这两种写法没有明显差别。小伙伴们优先掌握最通用的 push_back() 就可以了,等后面学习类与对象时再进一步体会 emplace_back() 的优势。

在指定位置插入元素

如果我们希望把新元素插到 vector 的开头或中间某个位置,而不是放在最后面,就需要使用 insert() 成员函数。

需要注意的是,insert() 的第 1 个参数不能直接写整数下标,而是要传入一个表示位置的 “迭代器”。这里大家暂时不需要深究迭代器的内部原理,先把它当成定位标记来使用即可。

我们可以把 容器名.begin() 看成指向第 1 个元素(下标 0)的起点。从起点往后走 i 步,写成 容器名.begin() + i,就刚好对应下标为 i 的位置。

1. 插入单个元素

在指定位置插入一个新元素时,我们需要传入目标位置和要插入的元素值。

语法:

容器名.insert(容器名.begin() + 下标, 元素值);

说明:

该语法会把 “元素值” 插入到指定下标的位置上,原本处于该位置以及后面的所有元素都会自动往后顺移一位。如果要插在最开头(下标 0),第 1 个参数直接写成 容器名.begin() 即可。

示例 4:插入单个元素

#include <iostream>
#include <vector>

int main() {
    std::vector<int> items = {20, 40};

    items.insert(items.begin(), 10);        // 在开头插入 10
    items.insert(items.begin() + 2, 30);    // 下标 2 处插入 30

    for (int item : items) {
        std::cout << item << ' ';
    }
    std::cout << '\n';
    return 0;
}

运行结果如下。

10 20 30 40

分析:

在这个例子中,items 一开始只有 20 和 40 两个元素,两次插入的过程如下:

  • 第 1 次插入:执行 items.insert(items.begin(), 10); 时,items.begin() 指向开头下标 0。把 10 插到最前面后,原来的 20 和 40 自动往后顺移一位,容器变为 {10, 20, 40}。
  • 第 2 次插入:执行 items.insert(items.begin() + 2, 30); 时,此时下标 2 对应元素 40 的位置。把 30 插进去之后,40 继续往后顺移一位,最终得到 {10, 20, 30, 40}。

初学者在使用 insert() 时要注意,不要把第 1 个位置参数直接写成整数下标,否则编译时会直接报错。

std::vector<int> items = {20, 40};

// 正确方式
items.insert(items.begin() + 1, 30);

// 错误方式
items.insert(1, 30);

2. 插入多个相同元素

除了每次插入一个元素,insert() 还支持在指定位置一次性连续插入多个相同的元素。

语法:

容器名.insert(容器名.begin() + 下标, 数量, 元素值);

说明:

在这个语法中,第 1 个参数依然是插入位置。第 2 个参数表示连续插入的个数,第 3 个参数表示要插入的具体数值。

示例 5:插入多个相同元素

#include <iostream>
#include <vector>

int main() {
    std::vector<int> items = {10, 50};

    items.insert(items.begin() + 1, 3, 0);    // 插入 3 个 0

    std::cout << "元素数量:" << items.size() << '\n';
    for (int item : items) {
        std::cout << item << ' ';
    }
    std::cout << '\n';
    return 0;
}

运行结果如下。

元素数量:5
10 0 0 0 50

分析:

items.insert(items.begin() + 1, 3, 0); 表示在下标 1 的位置连续插入 3 个 0。原本排在下标 1 处的 50 自动往后顺移了 3 位,容器的元素总数也随之变成了 5。

3. 插入一组元素列表

如果我们想在指定位置一次性插入多个 “各不相同” 的元素,可以直接把这组元素用花括号 {} 括起来传给 insert()。

语法:

容器名.insert(容器名.begin() + 下标, {元素1, 元素2, ...});

说明:

花括号中的各个元素会按照书写顺序,整体插入到指定下标的位置,原本位于该位置及之后的元素同样会自动往后顺移。

示例 6:插入一组不同元素

#include <iostream>
#include <vector>

int main() {
    std::vector<int> items = {10, 40};

    items.insert(items.begin() + 1, {20, 30});

    for (int item : items) {
        std::cout << item << ' ';
    }
    std::cout << '\n';
    return 0;
}

运行结果如下。

10 20 30 40

分析:

items.insert(items.begin() + 1, {20, 30}); 将 20 和 30 按顺序一起插入到了下标 1 的位置,省去了我们分多次调用 insert() 的麻烦。

提示 由于 vector 中的元素在内存中是连续存放的,调用 insert() 在开头或中间插入元素时,程序需要把插入点后面的所有元素依次往后搬移。如果数据量很大,频繁在前面插入会降低运行速度,日常开发应优先使用 push_back()。

给站长反馈

绿叶网正在不断完善中,小伙伴们如果发现任何问题,还望多多给站长反馈,谢谢!

邮箱:lvyenet@vip.qq.com

「绿叶网」服务号
绿叶网服务号放大
关注服务号,微信也能看教程。
绿叶网服务号