【C++】vector详解:接口使用、迭代器、内存理解、与模拟实现

news2024/10/1 13:24:13

文章目录

  • 1. 前言
  • 2. 内存角度 理解
  • 3. vector的使用
    • 定义 | 构造函数
    • vector iterator
    • vector 空间增长问题
    • vector 增删查改
    • vector 迭代器失效
      • 避免迭代器失效的建议
  • 4. 如何理解 二维动态vector
  • 5. 模拟实现 vector
  • 6. 相关文档

1. 前言

vector 是 C++ 标准模板库(STL)中最常用的动态数组容器之一。提供了一种灵活的方式来存储和管理元素,具备以下特点:

  1. 可变大小数组vector 是一种动态大小的数组容器,能够自动调整存储空间以适应元素增减。

  2. 连续存储:元素在内存中采用连续存储方式,支持高效的随机访问,时间复杂度为 O(1)。

  3. 动态分配:当新元素插入时,如果当前容量不足,vector 会分配一个更大的新数组,并将现有元素复制过去。虽然这个过程代价较高,但通过预留额外空间来减少频繁的重新分配。

  4. 空间管理:不同实现可能采取不同的策略来平衡时间复杂度和空间使用,通常以对数增长的方式增加容量。

  5. 操作效率:在末尾添加和删除元素的时间复杂度为 O(1),而在中间或开头进行插入和删除则为 O(n)。

  6. 迭代器优势vector 的迭代器支持随机访问,提供了比其他序列容器(如 listdeque)更好的性能表现。


2. 内存角度 理解

根据vector的文档介绍,我们知道:

vector是表示大小可变数组的序列容器;,本质是一个封装了动态分配数组的类

如何理解这个容器?

在这里插入图片描述

根据上图,vector申请的空间在堆上,并由标志位记录此时vector的总容量,当容量不够时根据规则进行扩容;


3. vector的使用

定义 | 构造函数

构造函数声明描述
vector()无参构造函数
vector(size_type n, const value_type& val = value_type())构造并初始化 n 个元素为 val
vector(const vector& x)拷贝构造函数
vector(InputIterator first, InputIterator last)使用迭代器范围进行初始化构造

vector iterator

接口说明描述
begin()获取第一个数据位置的 iterator / const_iterator
end()获取最后一个数据的下一个位置的 iterator / const_iterator
rbegin()获取最后一个数据位置的 reverse_iterator
rend()获取第一个数据前一个位置的 reverse_iterator

在这里插入图片描述


vector 空间增长问题

接口说明描述
size()获取数据个数
capacity()获取容量大小
empty()判断是否为空
resize(size_type n)改变 vector 的大小
reserve(size_type n)改变 vector 的容量
  • capacity() 接口 在 vsg++下分别运行会有以下结果:
    • vs下capacity是按1.5倍增长的,g++是按2倍增长的。
    • 即capacity的增长倍数并非固定的,而是根据具体需求定义的
    • vs是PJ版本STL,g++是SGI版本STL。
  • reserve只负责开辟空间,如果确定需要用多少空间,reserve可以缓解vector增容的代价缺陷问题。
  • resize在开空间的同时还会进行初始化,影响size

vector 增删查改

接口说明描述
push_back(const value_type& val)尾部插入元素 val
pop_back()尾部删除最后一个元素
find查找元素(算法模块实现,不是 vector 的成员接口)
insert(iterator position, const value_type& val)在指定位置之前插入元素 val
erase(iterator position)删除指定位置的元素
swap(vector& other)交换两个 vector 的数据空间
operator[](size_type index)像数组一样访问元素

vector 迭代器失效

  • 迭代器作为一种抽象数据类型,使算法在操作不同的数据结构时不必关心这些数据结构的具体实现;

  • 对于vector的迭代器来说,其底层本质是对指针进行了封装(原生态指针T*);因此对于迭代器失效,本质就是指针指向的空间被销毁了,因此指针失效了;

    • 使用被释放的空间,显然结果就是程序崩溃;
    • 即使用失效的迭代器,可能会导致程序崩溃

在使用 std::vector 时,有几种操作可能导致迭代器失效。下面是一些常见的情况及其代码示例:

  1. 插入元素

当向 vector 中插入元素时,如果当前容量不足,vector 会重新分配内存,导致所有迭代器失效。

#include <iostream>
#include <vector>

int main() {
    std::vector<int> vec = {1, 2, 3};
    auto it = vec.begin(); // 保存迭代器

    vec.push_back(4); // 可能导致迭代器失效

    // 使用失效的迭代器
    std::cout << *it << std::endl; // 未定义行为
    return 0;
}
  1. 删除元素

删除元素会导致被删除元素后的所有元素的迭代器失效。

#include <iostream>
#include <vector>

int main() {
    std::vector<int> vec = {1, 2, 3};
    auto it = vec.begin(); // 保存迭代器

    vec.erase(it); // 删除第一个元素,it 现在失效

    // 使用失效的迭代器
    std::cout << *it << std::endl; // 未定义行为
    return 0;
}
  1. 清空容器

调用 clear() 方法将删除 vector 中的所有元素,使得所有指向这些元素的迭代器失效。

#include <iostream>
#include <vector>

int main() {
    std::vector<int> vec = {1, 2, 3};
    auto it = vec.begin(); // 保存迭代器

    vec.clear(); // 清空容器,it 失效

    // 使用失效的迭代器
    std::cout << *it << std::endl; // 未定义行为
    return 0;
}
  1. 重新分配

如果通过改变 vector 的大小(例如 resize)并增加容量,现有迭代器也会失效。

#include <iostream>
#include <vector>

int main() {
    std::vector<int> vec = {1, 2, 3};
    auto it = vec.begin(); // 保存迭代器

    vec.resize(5); // 可能导致迭代器失效

    // 使用失效的迭代器
    std::cout << *it << std::endl; // 未定义行为
    return 0;
}

避免迭代器失效的建议

  • 重新获取迭代器:在进行插入或删除操作后,可以重新获取迭代器。
  • 使用 reserve:如果知道 vector 将要存储的元素数量,可以提前调用 reserve 来避免多次内存分配。
  • 使用范围for循环:尽量使用范围for循环来避免直接操作迭代器。

4. 如何理解 二维动态vector

我们以一个杨辉三角的例子举例,如果想打印高度为n的杨辉三角,可以用二维的vector,比如下面的代码:

void printPascalsTriangle(int numRows) {
    // 创建一个二维向量来存储杨辉三角
    std::vector<std::vector<int>> triangle(numRows);

    // 构建杨辉三角的每一行
    for (int i = 0; i < numRows; ++i) {
        triangle[i].resize(i + 1); // 调整每一行的大小以容纳相应数量的元素
        triangle[i][0] = 1; // 每行的第一个元素设为 1
        triangle[i][i] = 1; // 每行的最后一个元素设为 1

        // 填充当前行的中间元素
        for (int j = 1; j < i; ++j) {
            triangle[i][j] = triangle[i - 1][j - 1] + triangle[i - 1][j]; // 根据杨辉三角性质计算
        }
    }

    // 打印杨辉三角
    for (const auto& row : triangle) {
        for (int num : row) {
            std::cout << num << " "; // 输出当前行的每个数字
        }
        std::cout << std::endl; // 换行
    }
}

在刚初始化二维数组时,是这样的:
在这里插入图片描述
再填入相关数据后,是这样的:

在这里插入图片描述


5. 模拟实现 vector

👇 模拟实现部分在 👇

C++ vector类的模拟实现


6. 相关文档

  • 关于vector 的相关文档资料,可以参考下面的链接:
    • cppreference - vector
    • C++ Standard Library Documentation

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

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

相关文章

实例说明机器学习框架

机器学习框架是用于构建和训练机器学习模型的工具集合&#xff0c;它们提供了丰富的功能和库&#xff0c;帮助开发者简化模型开发流程。以下是几个流行的机器学习框架及其应用实例&#xff1a; 1. TensorFlow TensorFlow 是由 Google 开发的开源机器学习框架&#xff0c;广泛…

记一次使用python编写exp

使用的漏洞是企望制造ERP系统 RCE漏洞 POC POST /mainFunctions/comboxstore.action HTTP/1.1 Host: Cache-Control: max-age0 Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.…

影刀RPA实战:Excel拆分与合并工作表

1.影刀操作excel的优势 Excel&#xff0c;大家都不陌生&#xff0c;它是微软公司推出的一款电子表格软件&#xff0c;它是 Microsoft Office 套件的一部分。Excel 以其强大的数据处理、分析和可视化功能而闻名&#xff0c;广泛应用于商业、教育、科研等领域。可以说&#xff0…

生信初学者教程(二十):免疫浸润分析

文章目录 介绍加载R包导入数据所需函数堆积图箱线图热图相关性矩阵图输出结果总结介绍 在本章节中,将详细探讨免疫细胞的组成结构、其在不同个体和分组之间的相对丰度差异,并通过热图等可视化手段,对这些差异进行直观而深入的解析。这些分析将有助于科研人员更好地理解免疫细…

828华为云征文|华为云 Flexus X 实例之家庭娱乐中心搭建

话接上文《828华为云征文&#xff5c;华为云Flexus X实例初体验》&#xff0c;这次我们利用手头的 Flexus X 实例来搭建家庭影音中心和密码管理环境。 前置环境 为了方便小白用户甚至运维人员&#xff0c;我觉得现阶段的宝塔面板 和 1Panel 都是不错的选择。我这里以宝塔为例…

动态规划最低票价

前言&#xff1a;之前看到过这个题目归结到动态规划&#xff0c;当初还没什么思路&#xff0c;其实就是定义好dp [ i ] 为到第 i 个的最小费用就行&#xff0c;我们可以用upper_bound来优化我们的查找下标 题目地址 class Solution { public:int mincostTickets(vector<int&…

应对集运仓库丢件问题:集运系统的视频监控验货功能

在集运行业中&#xff0c;包裹丢件问题一直是令企业头疼的问题之一。客户投诉、纠纷处理不仅消耗了大量的人力物力&#xff0c;还可能影响企业的信誉和客户满意度。集运系统提供的视频验货服务&#xff0c;为解决这一难题提供了有效的解决方案。 一、集运仓库丢件问题的现状 集…

人口普查管理系统基于VUE+SpringBoot+Spring+SpringMVC+MyBatis开发设计与实现

目录 1. 系统概述 2. 系统架构设计 3. 技术实现细节 3.1 前端实现 3.2 后端实现 3.3 数据库设计 4. 安全性设计 5. 效果展示 ​编辑​编辑 6. 测试与部署 7. 示例代码 8. 结论与展望 一个基于 Vue Spring Boot Spring Spring MVC MyBatis 的人口普查管理…

MyBatis 学习总结

1. MyBatis 简介 MyBatis 是一款优秀的持久层框架&#xff0c;简化了 Java 程序与数据库的交互&#xff0c;通过 SQL 映射将 SQL 语句与 Java 对象关联起来。它基于传统 JDBC 的操作进行了封装&#xff0c;使得开发者无需手动编写复杂的 SQL 操作代码。 MyBatis 的特点包括&a…

《大厂算法冲锋:字符串数字求和的精妙之道》

前言 &#x1f680; 博主介绍&#xff1a;大家好&#xff0c;我是无休居士&#xff01;一枚任职于一线Top3互联网大厂的Java开发工程师&#xff01; &#x1f680; &#x1f31f; 欢迎大家关注我的微信公众号【JavaPersons】&#xff01;在这里&#xff0c;你将找到通往Java技…

云手机可以解决TikTok运营的哪些问题?

随着社交媒体的飞速发展&#xff0c;TikTok迅速崛起&#xff0c;成为个人和企业进行品牌宣传和内容创作的首选平台。然而&#xff0c;在运营TikTok账号的过程中&#xff0c;不少用户会遇到各种问题。本文将详细阐述云手机如何帮助解决这些问题。 1. 多账号管理的高效便捷 通过云…

[大语言模型-论文精读] 利用多样性进行大型语言模型预训练中重要数据的选择

[大语言模型-论文精读] 利用多样性进行大型语言模型预训练中重要数据的选择 论文信息&#xff1a; Harnessing Diversity for Important Data Selection in Pretraining Large Language Models Authors: Chi Zhang, Huaping Zhong, Kuan Zhang, Chengliang Chai, Rui Wang, X…

栈与队列相关知识(二)

目录 Java中栈&#xff08;Stack&#xff09; 一. 常用方法 1.push(E item) 2.pop() 3.peek() 4.empty() 二. 常用方法扩展 1. search(Object o) 2. clone() 3. contains(Object o) 4. size() 5. toArray() Java中队列&#xff08;Queue&#xff09; 一.常用方法&…

如何测试网络质量?

如何测试网络质量&#xff1f; 通过百度网盘分享的文件&#xff1a;winMTR 链接&#xff1a;https://pan.baidu.com/s/1Zfw4jciNhng35nfwBlF75Q 提取码&#xff1a;6622 –来自百度网盘超级会员V2的分享 下载WINMTR工具&#xff0c;在启动处输入www.baidu.com 判断方法&…

Trilium Notes笔记本地化部署与简单使用指南打造个人知识库

文章目录 前言1. 安装docker与docker-compose2. 启动容器运行镜像3. 本地访问测试4.安装内网穿透5. 创建公网地址6. 创建固定公网地址 前言 今天和大家分享一款在G站获得了26K的强大的开源在线协作笔记软件&#xff0c;Trilium Notes的中文版如何在Linux环境使用docker本地部署…

大模型新玩法!腾讯优图与上交大联手 利用公开知识提升大模型

腾讯优图实验室与上海交通大学的研究团队联手推出了一项革命性的知识增强方法&#xff0c;为大模型优化开辟了全新道路。这项创新技术摒弃了传统模型微调的局限&#xff0c;直接从开源数据中提取知识&#xff0c;大幅简化了模型优化流程&#xff0c;在多项任务中实现了超越现有…

【高性能内存池】central cache内存回收 7

thread cache中自由链表过长后&#xff0c;会将多出来的内存还给entral cache.thread cache还回来的内存可能不属于同一个span,因此&#xff0c;除了计算出要还到central cache的哪个桶之外&#xff0c;还需要计算出还到桶的哪个span。 1. 如何根据对象的地址找到对象的页号&am…

2024年9月中国干旱监测报告(FYDI-2.0指数)

目录 引言 旱情监测与分析 资料来源 引言 2024年9月&#xff0c;北方的降水逐渐增多&#xff0c;进入华西秋雨集中期&#xff0c;从青藏高原北部一直延伸到东北多地&#xff0c;常出现大范围的云带&#xff0c;西北地区的降雨强度较大。南方地区降水分布不均&#xff0c;受…

卷积神经网络(CNN)的计算量和参数怎么准确估计?

&#x1f349; CSDN 叶庭云&#xff1a;https://yetingyun.blog.csdn.net/ 1. 卷积层&#xff08;Convolutional Layer&#xff09; a) 计算量估计&#xff1a; 卷积层的 FLOPs 2 * H_out * W_out * C_in * C_out * K_h * K_w 详细解释&#xff1a; H_out, W_out&#xff…

linux:详解nohup命令

在 UNIX 和类 UNIX 操作系统&#xff08;如 Linux 和 macOS&#xff09;中&#xff0c;nohup 意图为后台运行且免疫挂断信号的命令&#xff0c;用于在用户注销&#xff08;logout&#xff09;或终端关闭后继续运行相应的进程。 基本语法 启动进程 nohup [COMMAND] [ARG...] …