当前位置: 首页 > news >正文

C++ Vector深度易错点指南(临时抱佛脚)(基础用法;进阶;高级;实战)

Vector

  • 1. Vector 基础概念
    • 1.1 内存结构
    • 1.2 初始化方法
    • 2.1 访问方式对比
    • 2.2 遍历流程
    • 3.1 扩容流程
    • 3.2 迭代器失效
      • 3.2.1 插入操作导致迭代器失效
      • 3.2.2 删除操作导致迭代器失效
      • 3.2.3 避免迭代器失效的建议
    • 4.1 排序与去重
      • 排序
      • 去重
      • 性能分析
    • 4.2 查找与条件删除
      • 查找
      • 条件删除
      • 性能分析
    • 5.1 内存模型
    • 5.2 正确初始化
      • 5.2.1 使用默认构造函数初始化
      • 5.2.2 使用初始化列表初始化
      • 5.2.3 使用构造函数初始化
      • 5.2.4 动态初始化
      • 错误示例 ❌
      • 修正方法 ✅
    • 6.1 预分配内存
      • 6.1.1 为什么需要预分配内存
      • 6.1.2 如何预分配内存
      • 6.1.3 性能对比
      • 6.1.4 注意事项
    • 6.2 避免不必要的拷贝
      • 6.2.1 使用引用传递
      • 6.2.2 使用 `std::move`
      • 6.2.3 使用 `emplace_back`
      • 6.2.4 避免临时对象的生成
    • 7.1 基础概念与初始化
    • 7.2 元素访问与遍历
    • 7.3 动态扩容与陷阱
    • 7.4 STL 算法与 Vector 结合
    • 7.5 二维 Vector
    • 7.6 进阶优化技巧

1. Vector 基础概念

1.1 内存结构

std::vector 是 C++ 标准模板库(STL)中的一个动态数组容器,其内存结构由三部分组成:

  • 动态数组指针 data:指向实际存储元素的连续内存区域,这是 std::vector 的核心,使得其能够通过下标快速访问元素。
  • 当前元素数量 size:记录当前存储在 std::vector 中的元素个数,反映了 std::vector 中实际使用的内存大小。
  • 预分配内存容量 capacity:表示 std::vector 已经分配的内存大小,通常大于或等于 size。当向 std::vector 中添加元素时,如果 size 超过了 capacitystd::vector 会自动扩容,重新分配更大的内存空间,并将原有元素复制到新内存中,这一过程会带来额外的性能开销。

这种内存结构使得 std::vector 兼具动态数组的灵活性和静态数组的高效性,能够根据需要自动调整大小,同时保证了对元素的快速随机访问。

1.2 初始化方法

std::vector 提供了多种初始化方法,以满足不同的使用场景:

  • 默认初始化:创建一个空的 std::vector,不包含任何元素,sizecapacity 均为 0。

    std::vector<int> v1;
    
  • 指定大小初始化:创建一个包含指定数量元素的 std::vector,所有元素均初始化为默认值(对于基本数据类型为 0,对于自定义类型则调用默认构造函数)。

    std::vector<int> v2(5); // 创建一个包含 5 个 0 的 vector
    
  • 指定大小和初始值初始化:创建一个包含指定数量元素的 std::vector,并将所有元素初始化为指定的值。

    std::vector<int> v3(3, 100); // 创建一个包含 3 个 100 的 vector
    
  • 列表初始化(C++11 及以上版本支持):使用花括号 {} 将一组元素初始化到 std::vector 中,这种方式直观且方便。

    std::vector<int> v4 = {1, 2, 3}; // 使用列表初始化
    
  • 拷贝初始化:通过已有的 std::vector 创建一个新的 std::vector,新 std::vector 中的元素是原 std::vector 中元素的副本。

    std::vector<int> v5(v4); // 拷贝初始化
    

这些初始化方法为用户提供了灵活的选择,能够根据具体需求快速创建并初始化 std::vector,从而提高编程效率。# 2. 元素访问与遍历

2.1 访问方式对比

std::vector 提供了多种访问元素的方式,每种方式都有其特点和适用场景。以下是几种常见的访问方式对比:

访问方式代码示例越界检查性能适用场景
下标操作符 []v[0]快速访问已知索引且确保安全时
at() 方法v.at(0)较慢需要安全访问时
迭代器*it快速访问遍历或算法操作
  • 下标操作符 []:通过索引直接访问元素,性能高,但不进行越界检查。如果索引超出范围,程序可能会崩溃或出现未定义行为。

    std::vector<int> v = {1, 2, 3};
    int first = v[0]; // 访问第一个元素
    
  • at() 方法:提供范围检查,如果索引超出范围,会抛出 std::out_of_range 异常。虽然安全性更高,但性能略低于下标操作符。

    std::vector<int> v = {1, 2, 3};
    int first = v.at(0); // 安全访问第一个元素
    
  • 迭代器:通过迭代器访问元素,适用于遍历整个容器或在算法中使用。迭代器提供了指针类似的语法,但不进行越界检查。

    std::vector<int> v = {1, 2, 3};
    for (auto it = v.begin(); it != v.end(); ++it) {std::cout << *it << " ";
    }
    

2.2 遍历流程

遍历 std::vector 的过程可以通过迭代器或范围 for 循环实现。以下是遍历的流程图和代码实现:

开始遍历
是否还有元素?
访问当前元素
移动到下一个元素
http://www.xdnf.cn/news/381079.html

相关文章:

  • PyTorch API 1 - 概述、数学运算、nn、实用工具、函数、张量
  • 【LangChain全景指南】构建下一代AI应用的开发框架
  • 数字相机的快门结构
  • not a genuine st device abort connection的问题
  • 实现三个采集板数据传送到一个显示屏的方案
  • null 的安全操作 vs 危险操作
  • Linux环境下基于Ncurses开发贪吃蛇小游戏
  • Java 内存模型 JMM
  • Edububtu 系统详解
  • Exploring Temporal Event Cues for Dense Video Captioning in Cyclic Co-Learning
  • 一个好用的快速学习的网站
  • python打卡day21
  • JavaScript基础-作用域概述
  • JDK10新特性
  • Apache Shiro 1.2.4 反序列化漏洞(CVE-2016-4437)
  • 二进制与十六进制数据转换:原理、实现与应用
  • DAY 21 常见的降维算法
  • 简述Web和HTTP
  • centos7.9上安装 freecad 指定安装位置
  • WinCC V7.2到V8.0与S71200/1500系列连接通讯教程以及避坑点
  • 码蹄集——向下取整(求立方根)、整理玩具、三角形斜边、完全平方数、个人所得税
  • MQTT协议介绍
  • 数据结构算法习题通关:树遍历 / 哈夫曼 / 拓扑 / 哈希 / Dijkstra 全解析
  • Python中的列表list使用详解
  • 重复的子字符串
  • 【ts】defineProps数组的类型声明
  • 人工智能100问☞第19问:什么是专家系统?
  • 自定义类型-结构体(二)
  • 基于ssm的超市库存商品管理系统(全套)
  • Vue.js框架的优缺点