C++中vector类型的介绍和使用

一、vector 类型的简介

  vector 是 C++ 标准模板库(STL)中最常用的顺序容器之一,底层实现为 动态数组。它提供动态增长、随机访问、高效末尾插入等特性。

1.1 基本介绍

#include <vector>
std::vector<int> numbers;

在这里插入图片描述

1.2 常见用法示例

初始化方式

std::vector<int> v1;                     // 空向量
std::vector<int> v2(5);                  // 5个默认值(0)
std::vector<int> v3(5, 42);              // 5个 42
std::vector<int> v4 = {1, 2, 3, 4};      // 列表初始化

常用操作

v1.push_back(10);       // 尾部添加元素
v1.pop_back();          // 删除最后一个元素
v1.size();              // 元素数量
v1.empty();             // 是否为空
v1.clear();             // 清空所有元素
v1.at(2);               // 安全访问第3个元素(带边界检查)
v1[2];                  // 快速访问第3个元素(无检查)

遍历方式

for (size_t i = 0; i < v1.size(); ++i)
    std::cout << v1[i] << std::endl;

for (int x : v1)        // C++11 范围循环
    std::cout << x << std::endl;

1.3 常见成员函数简表

在这里插入图片描述

二、vector 数据的插入

  std::vector 提供多种方式将数据插入容器中,适用于不同的使用场景(如单个元素插入、批量插入、自定义位置插入等)。

2.1 push_back() —— 在尾部插入一个元素

特点:时间复杂度均摊为 O(1)

示例:

std::vector<int> v;
v.push_back(10);
v.push_back(20);  // v = {10, 20}

2.2 emplace_back() —— 在尾部“就地”构造对象

特点:

  • 避免临时对象拷贝或移动
  • 构造更复杂类型推荐使用

示例:

std::vector<std::pair<int, std::string>> v;
v.emplace_back(1, "Alice");  // 直接构造 pair(1, "Alice")

2.3 insert() —— 在任意位置插入一个或多个元素

重载形式包括:

插入单个元素

std::vector<int> v = {1, 2, 4};
v.insert(v.begin() + 2, 3);  // v = {1, 2, 3, 4}

插入多个相同元素

v.insert(v.begin(), 3, 100);  // 插入3个100在开头

插入另一 vector 的一段范围

std::vector<int> v1 = {1, 2};
std::vector<int> v2 = {10, 20, 30};
v1.insert(v1.end(), v2.begin(), v2.end());  // v1 = {1, 2, 10, 20, 30}

2.4 emplace() —— 在任意位置就地构造对象

类似于 insert(),但对象是“就地构造”而非拷贝。

示例:

std::vector<std::pair<int, std::string>> v;
v.emplace(v.begin(), 1, "Bob");  // 插入 pair(1, "Bob") 到开头

2.5 assign() —— 替换整个 vector 的内容

注意这是替换整个内容,不是插入。

std::vector<int> v;
v.assign(5, 42);  // v = {42, 42, 42, 42, 42}

插入方式对比表
在这里插入图片描述

三、vector 数据的遍历

3.1 范围-based for 循环(C++11 起)

#include <vector>
#include <iostream>

std::vector<int> vec = {1, 2, 3, 4, 5};

for (int value : vec) {
    std::cout << value << " ";
}

3.2 使用下标访问

for (size_t i = 0; i < vec.size(); ++i) {
    std::cout << vec[i] << " ";
}

也可以用 at() 提供边界检查:

for (size_t i = 0; i < vec.size(); ++i) {
    std::cout << vec.at(i) << " ";
}

3.3 使用迭代器

for (std::vector<int>::iterator it = vec.begin(); it != vec.end(); ++it) {
    std::cout << *it << " ";
}

如果不需要修改数据,可使用 const_iterator:

for (std::vector<int>::const_iterator it = vec.cbegin(); it != vec.cend(); ++it) {
    std::cout << *it << " ";
}

3.4 使用 std::for_each 和 Lambda(C++11 起)

#include <algorithm>

std::for_each(vec.begin(), vec.end(), [](int value) {
    std::cout << value << " ";
});

四、vector 数据的删除

4.1 删除尾部元素:pop_back()

std::vector<int> vec = {1, 2, 3};
vec.pop_back(); // 删除最后一个元素(3)

4.2 按下标删除一个元素:erase(iterator)

std::vector<int> vec = {10, 20, 30, 40};
vec.erase(vec.begin() + 2); // 删除索引为2的元素(30)

4.3 删除一个区间:erase(begin, end)

std::vector<int> vec = {1, 2, 3, 4, 5};
vec.erase(vec.begin() + 1, vec.begin() + 4); // 删除 2, 3, 4
// 结果为 vec = {1, 5}

4.4 按值删除(配合 remove)

#include <algorithm>

std::vector<int> vec = {1, 2, 3, 2, 4};
// 删除所有值为 2 的元素
vec.erase(std::remove(vec.begin(), vec.end(), 2), vec.end());
// 结果为 vec = {1, 3, 4}

注意:std::remove 不是真正删除,而是将不符合条件的元素移到后面,返回“新逻辑末尾”,再用 erase 删除尾部的冗余数据。

4.5 按条件删除(用 lambda)

// 删除所有大于3的元素
vec.erase(std::remove_if(vec.begin(), vec.end(), [](int x) {
    return x > 3;
}), vec.end());

4.6 清空整个 vector:clear()

vec.clear(); // 删除所有元素,size() 为 0

4.7 删除自定义类型的元素(按值或条件)

struct Person {
    std::string name;
    int age;
};

std::vector<Person> people = {
    {"Alice", 25}, {"Bob", 30}, {"Charlie", 25}
};

// 删除所有 age 为 25 的人
people.erase(std::remove_if(people.begin(), people.end(), [](const Person& p) {
    return p.age == 25;
}), people.end());

4.8 删除某个元素再次遍历

方法 1:使用 erase + iterator,正确方式如下:

#include <vector>
#include <iostream>

int main() {
    std::vector<int> vec = {1, 2, 3, 2, 4};

    for (auto it = vec.begin(); it != vec.end(); ) {
        if (*it == 2) {
            it = vec.erase(it);  // erase 返回新的 iterator,指向被删元素的下一个位置
        } else {
            ++it;
        }
    }

    // 再次遍历
    for (int val : vec) {
        std::cout << val << " ";
    }
    return 0;
}

方法 2:先删除,再单独遍历(更清晰):

vec.erase(std::remove(vec.begin(), vec.end(), 2), vec.end());

// 再次遍历
for (int val : vec) {
    std::cout << val << " ";
}

错误示例(不要这样做):

for (auto it = vec.begin(); it != vec.end(); ++it) {
    if (*it == 2) {
        vec.erase(it); // ❌ it 会失效,下一次 ++it 就是未定义行为
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值