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

news2025/6/10 12:07:12

文章目录

    • 一、vector 类型的简介
      • 1.1 基本介绍
      • 1.2 常见用法示例
      • 1.3 常见成员函数简表
    • 二、vector 数据的插入
      • 2.1 push_back() —— 在尾部插入一个元素
      • 2.2 emplace_back() —— 在尾部“就地”构造对象
      • 2.3 insert() —— 在任意位置插入一个或多个元素
      • 2.4 emplace() —— 在任意位置就地构造对象
      • 2.5 assign() —— 替换整个 vector 的内容
    • 三、vector 数据的遍历
      • 3.1 范围-based for 循环(C++11 起)
      • 3.2 使用下标访问
      • 3.3 使用迭代器
      • 3.4 使用 std::for_each 和 Lambda(C++11 起)
    • 四、vector 数据的删除
      • 4.1 删除尾部元素:pop_back()
      • 4.2 按下标删除一个元素:erase(iterator)
      • 4.3 删除一个区间:erase(begin, end)
      • 4.4 按值删除(配合 remove)
      • 4.5 按条件删除(用 lambda)
      • 4.6 清空整个 vector:clear()
      • 4.7 删除自定义类型的元素(按值或条件)
      • 4.8 删除某个元素再次遍历

一、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 就是未定义行为
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2406597.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

CVE-2023-25194源码分析与漏洞复现(Kafka JNDI注入)

漏洞概述 漏洞名称&#xff1a;Apache Kafka Connect JNDI注入导致的远程代码执行漏洞 CVE编号&#xff1a;CVE-2023-25194 CVSS评分&#xff1a;8.8 影响版本&#xff1a;Apache Kafka 2.3.0 - 3.3.2 修复版本&#xff1a;≥ 3.4.0 漏洞类型&#xff1a;反序列化导致的远程代…

Copilot for Xcode (iOS的 AI辅助编程)

Copilot for Xcode 简介Copilot下载与安装 体验环境要求下载最新的安装包安装登录系统权限设置 AI辅助编程生成注释代码补全简单需求代码生成辅助编程行间代码生成注释联想 代码生成 总结 简介 尝试使用了Copilot&#xff0c;它能根据上下文补全代码&#xff0c;快速生成常用…

Axure零基础跟我学:展开与收回

亲爱的小伙伴,如有帮助请订阅专栏!跟着老师每课一练,系统学习Axure交互设计课程! Axure产品经理精品视频课https://edu.csdn.net/course/detail/40420 课程主题:Axure菜单展开与收回 课程视频:

RabbitMQ 各类交换机

为什么要用交换机&#xff1f; 交换机用来路由消息。如果直发队列&#xff0c;这个消息就被处理消失了&#xff0c;那别的队列也需要这个消息怎么办&#xff1f;那就要用到交换机 交换机类型 1&#xff0c;fanout&#xff1a;广播 特点 广播所有消息​​&#xff1a;将消息…

高保真组件库:开关

一:制作关状态 拖入一个矩形作为关闭的底色:44 x 22,填充灰色CCCCCC,圆角23,边框宽度0,文本为”关“,右对齐,边距2,2,6,2,文本颜色白色FFFFFF。 拖拽一个椭圆,尺寸18 x 18,边框为0。3. 全选转为动态面板状态1命名为”关“。 二:制作开状态 复制关状态并命名为”开…

未授权访问事件频发,我们应当如何应对?

在当下&#xff0c;数据已成为企业和组织的核心资产&#xff0c;是推动业务发展、决策制定以及创新的关键驱动力。然而&#xff0c;未授权访问这一隐匿的安全威胁&#xff0c;正如同高悬的达摩克利斯之剑&#xff0c;时刻威胁着数据的安全&#xff0c;一旦触发&#xff0c;便可…

欢乐熊大话蓝牙知识17:多连接 BLE 怎么设计服务不会乱?分层思维来救场!

多连接 BLE 怎么设计服务不会乱&#xff1f;分层思维来救场&#xff01; 作者按&#xff1a; 你是不是也遇到过 BLE 多连接时&#xff0c;调试现场像网吧“掉线风暴”&#xff1f; 温度传感器连上了&#xff0c;心率带丢了&#xff1b;一边 OTA 更新&#xff0c;一边通知卡壳。…

Element-Plus:popconfirm与tooltip一起使用不生效?

你们好&#xff0c;我是金金金。 场景 我正在使用Element-plus组件库当中的el-popconfirm和el-tooltip&#xff0c;产品要求是两个需要结合一起使用&#xff0c;也就是鼠标悬浮上去有提示文字&#xff0c;并且点击之后需要出现气泡确认框 代码 <el-popconfirm title"是…

Selenium 查找页面元素的方式

Selenium 查找页面元素的方式 Selenium 提供了多种方法来查找网页中的元素&#xff0c;以下是主要的定位方式&#xff1a; 基本定位方式 通过ID定位 driver.find_element(By.ID, "element_id")通过Name定位 driver.find_element(By.NAME, "element_name"…

OPENCV图形计算面积、弧长API讲解(1)

一.OPENCV图形面积、弧长计算的API介绍 之前我们已经把图形轮廓的检测、画框等功能讲解了一遍。那今天我们主要结合轮廓检测的API去计算图形的面积&#xff0c;这些面积可以是矩形、圆形等等。图形面积计算和弧长计算常用于车辆识别、桥梁识别等重要功能&#xff0c;常用的API…

spring boot使用HttpServletResponse实现sse后端流式输出消息

1.以前只是看过SSE的相关文章&#xff0c;没有具体实践&#xff0c;这次接入AI大模型使用到了流式输出&#xff0c;涉及到给前端流式返回&#xff0c;所以记录一下。 2.resp要设置为text/event-stream resp.setContentType("text/event-stream"); resp.setCharacter…

二叉树-144.二叉树的前序遍历-力扣(LeetCode)

一、题目解析 对于递归方法的前序遍历十分简单&#xff0c;但对于一位合格的程序猿而言&#xff0c;需要掌握将递归转化为非递归的能力&#xff0c;毕竟递归调用的时候会调用大量的栈帧&#xff0c;存在栈溢出风险。 二、算法原理 递归调用本质是系统建立栈帧&#xff0c;而非…

【技巧】dify前端源代码修改第一弹-增加tab页

回到目录 【技巧】dify前端源代码修改第一弹-增加tab页 尝试修改dify的前端源代码&#xff0c;在知识库增加一个tab页"HELLO WORLD"&#xff0c;完成后的效果如下 [gif01] 1. 前端代码进入调试模式 参考 【部署】win10的wsl环境下启动dify的web前端服务 启动调试…

Java设计模式:责任链模式

一、什么是责任链模式&#xff1f; 责任链模式&#xff08;Chain of Responsibility Pattern&#xff09; 是一种 行为型设计模式&#xff0c;它通过将请求沿着一条处理链传递&#xff0c;直到某个对象处理它为止。这种模式的核心思想是 解耦请求的发送者和接收者&#xff0c;…

初探用uniapp写微信小程序遇到的问题及解决(vue3+ts)

零、关于开发思路 (一)拿到工作任务,先理清楚需求 1.逻辑部分 不放过原型里说的每一句话,有疑惑的部分该问产品/测试/之前的开发就问 2.页面部分(含国际化) 整体看过需要开发页面的原型后,分类一下哪些组件/样式可以复用,直接提取出来使用 (时间充分的前提下,不…

云原生时代的系统设计:架构转型的战略支点

&#x1f4dd;个人主页&#x1f339;&#xff1a;一ge科研小菜鸡-CSDN博客 &#x1f339;&#x1f339;期待您的关注 &#x1f339;&#x1f339; 一、云原生的崛起&#xff1a;技术趋势与现实需求的交汇 随着企业业务的互联网化、全球化、智能化持续加深&#xff0c;传统的 I…

python可视化:俄乌战争时间线关键节点与深层原因

俄乌战争时间线可视化分析&#xff1a;关键节点与深层原因 俄乌战争是21世纪欧洲最具影响力的地缘政治冲突之一&#xff0c;自2022年2月爆发以来已持续超过3年。 本文将通过Python可视化工具&#xff0c;系统分析这场战争的时间线、关键节点及其背后的深层原因&#xff0c;全面…

C# WPF 左右布局实现学习笔记(1)

开发流程视频&#xff1a; https://www.youtube.com/watch?vCkHyDYeImjY&ab_channelC%23DesignPro Git源码&#xff1a; GitHub - CSharpDesignPro/Page-Navigation-using-MVVM: WPF - Page Navigation using MVVM 1. 新建工程 新建WPF应用&#xff08;.NET Framework) 2.…

Linux入门(十五)安装java安装tomcat安装dotnet安装mysql

安装java yum install java-17-openjdk-devel查找安装地址 update-alternatives --config java设置环境变量 vi /etc/profile #在文档后面追加 JAVA_HOME"通过查找安装地址命令显示的路径" #注意一定要加$PATH不然路径就只剩下新加的路径了&#xff0c;系统很多命…

【QT控件】显示类控件

目录 一、Label 二、LCD Number 三、ProgressBar 四、Calendar Widget QT专栏&#xff1a;QT_uyeonashi的博客-CSDN博客 一、Label QLabel 可以用来显示文本和图片. 核心属性如下 代码示例: 显示不同格式的文本 1) 在界面上创建三个 QLabel 尺寸放大一些. objectName 分别…