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

std::vector

std::vector是C++标准库中一个非常强大的容器类,它提供了动态数组的功能。std::vector可以自动调整大小,提供了随机访问的能力,同时还支持在序列的尾部高效地添加和删除元素。

当创建一个空的std::vector对象时,它不分配任何内存,大小是0。当开始添加元素时,std::vector会动态分配内存。通常情况下,第一次分配的内存大小由具体的实现决定,但通常是一个小的初始值,比如16或32个元素大小的内存块。

当元素数量超过当前内存容量时,std::vector将重新分配内存,并将元素从旧的内存块复制到新的内存块中。新的内存块的大小通常是当前元素数量的两倍或更多,具体取决于具体的实现和策略。重新分配内存时,可能会有一些额外的内存开销,因为需要考虑到内存对齐和内存管理的一些细节。

std::vector的特性:

  • 动态大小:std::vector的大小可以动态变化,能够根据需要自动扩容
  • 连续存储:像静态数组一样,内部使用连续的内存存储元素,这使得元素访问速度很快
  • 模板类:std::vector是一个模板类,可以存储任何类型的数据

std::vector提供了一系列成员函数来操作和管理动态数组:

  • 构造函数和析构函数

    • std::vector():构造一个空的向量

    • std::vector(size_type n, const T& value = T()):构造一个包含n个具有value值的元素的向量

    • std::vector(const std::vector& other):拷贝构造函数,深拷贝,会复制other中的元素,并存储到新的向量中

    • std::vector(std::vector&& other) noexcept:移动构造函数,将另一个已存在的vector对象的资源移动到新创建的vector中,而不是进行深拷贝

    • ~std::vector():析构函数,释放向量所占用的内存

      std::vector<int> vec;  // 创建vec向量std::vector<std::string> vec(5, "A");  // 创建一个向量,该向量有5个元素,每个元素的值都是"A"std::vector<int> vec = {1, 2, 3, 4, 5};  // 创建向量vec,并进行初始化
      std::vector<int> new_vec(vec);  // 创建新的向量new_vec,并深拷贝vec中的元素std::vector<int> vec = {1, 2, 3, 4, 5};
      std::vector<int> new_vec(std::move(vec));  // 创建新的向量new_vec,并将vec的资源移动到new_vec在C++标准库中,std::vector的析构函数是隐式生成的,如果用户没有自定义,将会使用编译器默认生成的析构函数。默认情况下,析构函数会按顺序释放元素,然后释放分配的内存。因此,std::vector在其生命周期结束时会自动执行析构函数,确保动态分配的内存被正确释放,从而避免内存泄漏。
      
  • 元素访问

    • operator[]:通过索引访问向量的元素

    • at(value):通过索引访问向量的元素,带边界检查

    • front():访问向量的第一个元素

    • back():访问向量的最后一个元素

    • data():返回一个指向向量第一个元素的指针

      std::vector<int> vec{0, 1, 2, 3, 4, 5};  // 创建向量vec,并进行初始化std::cout << vec[3] << std::endl;  // 3
      std::cout<< vec.at(3) << std::endl;  // 3
      std::cout<< vec.front() << std::endl;  // 0
      std::cout<< vec.back() << std::endl;  // 5
      int* ptr = vec.data();
      for (size_t i = 0; i < vec.size(); ++i) {std::cout << *(ptr + i) << " ";  // 0 1 2 3 4 5std::cout << ptr[i] << " ";  // 0 1 2 3 4 5
      }
      
  • 修改器

    • push_back(const T& value):在向量的末尾添加一个元素

    • pop_back():移除向量的最后一个元素

    • emplace_back(Args&&… args):就地构造一个元素,避免额外的复制或移动

    • insert(const_iterator pos, const T& value):在指定位置插入一个元素

    • erase(const_iterator pos):删除指定位置或指定范围内的元素

    • resize():调整向量的大小

    • clear():清除向量中的所有元素

      std::vector<std::string> vec{"A", "B", "C"};
      for (auto value : vec) {std::cout << value << std::endl;  // A B C
      }vec.push_back("D");  // 在向量末尾添加一个元素
      for (auto value : vec) {std::cout << value << std::endl;  // A B C D
      }vec.pop_back();  // 移除向量的最后一个元素
      for (auto value : vec) {std::cout << value << std::endl;  // A B C
      }vec.emplace_back("E");  // 在向量末尾添加一个元素
      for (auto value : vec) {std::cout << value << std::endl;  // A B C E
      }vec.insert(vec.begin() + 1, "F");  // 在索引为1的位置插入元素"F"
      for (auto value : vec) {std::cout << value << std::endl;  // A F B C E
      }std::string values[] = {"X", "Y", "Z"};
      vec.insert(vec.end(), std::begin(values), std::end(values));  // 在向量末尾插入一系列元素
      for (auto value : vec) {std::cout << value << std::endl;  // A F B C E X Y Z
      }vec.erase(vec.begin() + 1);  // 删除索引为1的元素
      for (auto value : vec) {std::cout << value << std::endl;  // A B C E X Y Z
      }vec.erase(vec.begin() + 4, vec.end());  // 删除一系列元素,范围包括索引为4的元素到最后一个元素;范围是左闭右开,vec.end()指向末尾元素的后一位,因此囊括了末尾元素
      for (auto value : vec) {std::cout << value << std::endl;  // A B C E
      }vec.resize(3);  // 调整向量大小,新的向量变小了,会删除多余的元素;A B C
      vec.resize(5);  // 调整向量大小,新的向量变大了,会添加新的元素,默认构造;A B C 空值 空值
      vec.resize(7, "E");  // 调整向量大小,新的向量变大了,会添加指定了值的元素;A B C 空值 空值 E Evec.clear();  // 清除向量中的所有元素;向量变为空,但分配的内存不会被释放
      std::cout << vec.size() << std::endl;  // 0/*
      push_back函数用于在向量的末尾添加一个元素,这个元素可以是值,也可以是另一个向量中元素的引用或指针。
      emplace_back函数用于在向量的末尾就地构造一个元素,它可以避免临时对象的创建,而是直接将参数传递给构造函数,从而提高效率。
      emplace_back通常比push_back更高效,因为它避免了复制或移动操作,直接在向量的末尾就地构造元素。
      如果需要构造一个对象并将其添加到向量的末尾,emplace_back是更好的选择;如果需要添加一个已经存在的对象,push_back是合适的。
      */
      
  • 容量

    • empty():判断向量是否为空,返回一个布尔值

    • size():返回向量中元素的数量

    • max_size():返回向量能容纳的最大元素数量

    • capacity():返回向量当前的容量

    • reserve(size_type new_cap):改变向量的容量

    • shrink_to_fit():减小向量的容量以适应其大小

      std::vector<int> vec = {1, 2, 3, 4, 5};
      bool is_empty = vec.empty();  // 如果向量为空,返回1;如果向量不为空,返回0 
      std::cout << is_empty << std::endl;  // 输出0vec.pop_back();  // 移除末尾元素
      std::cout << vec.size() << std::endl;  // 输出4,向量中还有4个元素
      std::cout << vec.capacity() << std::endl;  // 输出5,虽然移除了一个元素,但占用的内存空间并没有释放,因此容量为5
      std::cout << vec.max_size() << std::endl;  // 4611686018427387903,向量能容纳的最大元素数量vec.reserve(10);  // 将vec的容量改为10
      std::cout << vec.capacity() << std::endl;  // 输出10vec.shrink_to_fit();  // 改变容量以适应向量的大小
      std::cout << vec.capacity() << std::endl;  // 输出4,因为向量中有4个元素,因此容量会自动适应向量的大小
      
  • 迭代器

    • begin():返回指向向量第一个元素的迭代器

    • end():返回指向向量尾后一位的迭代器

    • cbegin():返回指向向量第一个元素的const迭代器

    • cend():返回指向向量尾后一位的const迭代器

    • rbegin():返回指向向量最后一个元素的反向迭代器

    • rend():返回指向向量首前一位的反向迭代器

    • crbegin():返回指向向量最后一个元素的const反向迭代器

    • crend(): 返回指向向量首前一位的const反向迭代器

      std::vector<int> vec{1, 2, 3, 4, 5};
      for (auto it = vec.begin(); it != vec.end(); it++) {std::cout << *it << std::endl;  // 1 2 3 4 5
      }for (auto it = vec.cbegin(); it != vec.cend(); it++) {std::cout << *it << std::endl;  // 1 2 3 4 5
      }for (auto it = vec.rbegin(); it != vec.rend(); it++) {std::cout << *it << std::endl;  // 5 4 3 2 1 
      }for (auto it = vec.crbegin(); it != vec.crend(); it++) {std::cout << *it << std::endl;  // 5 4 3 2 1 
      }
      
  • 数据操作/赋值操作

    • assign(size_type n, const T& value):替换向量的内容为n个value元素

    • swap(std::vector& other):交换向量的内容

      std::vector<int> vec = {1, 2, 3, 4, 5};
      std::vector<int> new_vec = {6, 7, 8, 9};vec.assign(new_vec.begin(), new_vec.end());  // 将new_vec的全部元素赋给vec
      for (auto value : vec) {std::cout << value << std::endl;  // 6 7 8 9
      }vec.assign(5, 10);  // 将5个10赋给vec
      for (auto value : vec) {std::cout << value << std::endl;  // 10 10 10 10 10
      }
      
      std::vector<int> vec = {1, 2, 3, 4, 5};
      std::vector<int> new_vec = {6, 7, 8, 9};vec.swap(new_vec);  // 将vec与new_vec的元素互相交换
      for (auto value : vec) {std::cout << value << std::endl;  // 6 7 8 9
      }for (auto value : new_vec) {std::cout << value << std::endl;  // 1 2 3 4 5
      }
      
  • 查找操作

    • find(const T& value):查找第一个等于value的元素

    • lower_bound(const T& value):查找第一个不小于value的元素

    • upper_bound(const T& value):查找第一个大于value的元素

      std::vector<int> vec{3, 2, 1, 4, 5};auto it = std::find(vec.begin(), vec.end(), 3);  // std::find函数用于在向量中查找特定值,并返回指向找到的元素的迭代器,如果未找到,则返回尾后迭代器
      std::cout << *it << std::endl;  // 输出3auto it = std::find(vec.begin(), vec.end(), 0);  // 要查找的0不在向量中,因此返回尾后迭代器,即指向向量尾后一位的迭代器
      std::cout << *(it - 1) << std::endl;  // 输出5,尾后迭代器前一个元素就是向量的末尾元素
      
      std::vector<int> vec{3, 2, 1, 4, 5};std::sort(vec.begin(), vec.end());  // 对向量进行排序,默认为升序
      for (auto value : vec) {std::cout << value << std::endl;  // 1 2 3 4 5
      }std::sort(vec.begin(), vec.end(), std::greater<int>());  // 对向量进行降序排序
      for (auto value : vec) {std::cout << value << std::endl;  // 5 4 3 2 1
      }std::sort(vec.begin(), vec.end(), [](int a, int b) { return a > b; });  // 使用lambda表达式实现降序排序
      for (auto value : vec) {std::cout << value << std::endl;  // 5 4 3 2 1
      }/*
      std::sort是一个非常强大的标准库算法,用于对序列进行排序。它可以对数组、向量(std::vector)、字符串(std::string)等容器进行排序。std::sort函数定义在<algorithm>头文件中。
      */
      
      std::vector<int> vec{3, 4, 6, 7, 8};auto it = std::lower_bound(vec.begin(), vec.end(), 4);  // 找出第一个不小于4的元素,并返回指向该元素的迭代器
      std::cout << *it << std::endl;  // 输出4auto it = std::lower_bound(vec.begin(), vec.end(), 5);  // 找出第一个不小于5的元素,并返回指向该元素的迭代器
      std::cout << *it << std::endl;  // 输出6auto it = std::upper_bound(vec.begin(), vec.end(), 4);  // 找出第一个大于4的元素,并返回指向该元素的迭代器
      std::cout << *it << std::endl;  // 输出6
      
  • 运算符重载

    • 赋值运算符 =:用于将一个向量的内容赋值给另一个向量

    • 比较运算符 ==、!=、<、>、<=、>=:用于比较两个向量的内容

      std::vector<int> vec1 = {1, 2, 3};
      std::vector<int> vec2;
      vec2 = vec1;  // 将vec1的内容赋给vec2
      for (auto value : vec2) {std::cout << value << std::endl;  // 1 2 3
      }
      
      std::vector<int> vec1 = {1, 2, 3};
      std::vector<int> vec2 = {1, 2, 4};
      bool res = vec1 <= vec2;
      std::cout << res << std::endl;  // 输出1
      
  • 特殊操作

    • emplace(const_iterator pos, Args&&… args):在指定位置就地构造一个元素,它可以直接将参数传给构造函数,而不需要提前创建一个对象

      std::vector<int> vec = {1, 2, 3, 4, 5};vec.emplace(vec.begin(), 0);  // 在vec的第一个位置就地插入一个元素0
      for (auto value : vec) {std::cout << value << std::endl;  // 0 1 2 3 4 5
      }
      

相关文章:

std::vector

std::vector是C标准库中一个非常强大的容器类&#xff0c;它提供了动态数组的功能。std::vector可以自动调整大小&#xff0c;提供了随机访问的能力&#xff0c;同时还支持在序列的尾部高效地添加和删除元素。 当创建一个空的std::vector对象时&#xff0c;它不分配任何内存&a…...

Java Web 之 Cookie 详解

在 JavaWeb 开发中&#xff0c;Cookie 就像网站给浏览器贴的小纸条&#xff0c;用于记录一些用户信息或状态&#xff0c;方便下次访问时识别用户身份或进行个性化服务。 也可以这么理解&#xff1a; 场景一&#xff1a;想象一下&#xff0c;你去一家咖啡店&#xff0c;店员认…...

linux系统下让.py文件开机自启动

一 创建服务文件 1、打开终端 2、切换到root用户 sudo su3、创建一个新的systemd服务文件 nano /etc/systemd/system/total_test0619.service 4、在服务文件中添加以下内容 [Unit] DescriptionRun total_test0619.py at startup[Service] Typesimple ExecStart/usr/bin/n…...

linux远程桌面:xrdp 安装失败

window 如何远程 Linux 桌面 安装xrdp yum install xrdpsystemctl start xrdp 如果找不到软件包&#xff0c;就安装epel源&#xff0c;最好改成国内镜像的 在 /etc/yum.repos.d/ 下创建epel.repo,内容如下 [epel] nameExtra Packages for Enterprise Linux 7 - $basearch …...

9.30Python基础-元组(补充)、字典、集合

Python元组&#xff08;tuple&#xff09;补充 1、元组的不可变性 元组&#xff08;tuple&#xff09;是Python中的一种内置数据类型&#xff0c;用于存储不可变的序列。虽然元组本身不可变&#xff0c;但元组内的元素如果是可变对象&#xff08;如列表&#xff09;&#xff…...

桥接模式和NET模式的区别

桥接模式和NET模式的区别 NAT模式&#xff1a; NAT&#xff1a;网络地址转换&#xff08;模式&#xff09;&#xff1a;借助宿主机来上网&#xff0c;没桥接那么麻烦&#xff0c;只用配置DNS即可。 缺点&#xff1a;扎根于宿主机&#xff0c;不能和局域网内其它真实的主机进行…...

Pigar:Python 项目的依赖管理利器

&#x1f31f; 引言 在Python项目开发过程中&#xff0c;依赖管理是一个不可忽视的环节。一个精确且易于维护的requirements.txt文件对于项目的部署和协作至关重要。今天&#xff0c;我们将介绍一款名为Pigar的自动生成requirements.txt文件的依赖管理工具&#xff0c;它通过一…...

泰勒图 ——基于相关性与标准差的多模型评价指标可视化比较-XGBoost、sklearn

1、基于相关性与标准差的多模型评价指标可视化比较 # 数据读取并分割 import pandas as pd import numpy as np import matplotlib.pyplot as plt from sklearn.model_selection import train_test_split plt.rcParams[font.family] = Times New Roman plt.rcParams[axes.unic…...

记录|Modbus-TCP产品使用记录【摩通传动】

目录 前言一、摩通传动实验图1.1 配置软件 IO_Studio1.2 测试软件Modbus Poll1.2.1 读写设置测试1.2.2 AI信号的读取 1.3 对应的C#连接Modbus的测试代码如下【自制&#xff0c;仅供参考】1.4 最终实验图 更新时间 前言 参考文章&#xff1a; 自己需要了解和对比某些产品的Modbu…...

工业交换机的RMON

工业交换机在现代网络中扮演着至关重要的角色&#xff0c;它不仅负责数据的高效传输&#xff0c;还具备强大的监控和管理能力。其中&#xff0c;RMON&#xff08;远程监控&#xff09;功能使得交换机的性能得以进一步提升&#xff0c;成为网络管理的重要工具。RMON提供了一种先…...

生态遥感数据下载分享

中国土壤湿度/土壤水分数据集&#xff08;2000-2020&#xff09; 下载网站&#xff1a;https://poles.tpdc.ac.cn/zh-hans/data/49b22de9-5d85-44f2-a7d5-a1ccd17086d2/#:~:text%E6%88%91%E4%BB%AC%E6%8F%90%E4%BE%9B%E4%BA%86%E4%B8%AD%E5%9B%BD%E8%8C%83 note: The data can …...

ECharts 快速使用

最终效果 使用介绍 echarts图表的绘制&#xff0c;大体分为三步&#xff1a; 根据 DOM实例&#xff0c;通过 echarts.init方法&#xff0c;生成 echarts实例构建 options配置对象&#xff0c;整个echarts的样式&#xff0c;皆有该对象决定最后通过实例.setOption方法&#xf…...

进程--消息队列和共享内存

目录 消息队列 创建消息队列 删除消息队列 发送消息和接收 消息队列 消息队列就是一个消息的列表&#xff0c;进程可以在消息队列中添加消息和的读取消息 消息队列具有FIFO的特性&#xff0c;具有无名管道与有名管道各自的优势&#xff0c;可以支持任意两个进程的进程间通讯…...

useCallback()

官网直达&#xff1a;https://zh-hans.react.dev/reference/react/useCallback 点击按钮&#xff0c;子组件会重新渲染 import { memo, useState, useCallback } from react;const Child (props) > {console.log(我是子组件&#xff01;我在渲染呢&#xff01;&#xff0…...

Python面试题精选及解析--第二篇

在Python的面试中&#xff0c;除了基础语法和常用库的知识外&#xff0c;面试官往往还会通过一系列的问题来考察应聘者的逻辑思维、问题解决能力以及项目经验。以下是一些精心挑选的Python面试题及其详细答案&#xff0c;旨在帮助求职者更好地准备面试。 面试题一&#xff1a;…...

Linux操作常用问题

目录 Ubuntu操作问题vi编辑方向键键盘乱码回退键不能使用的问题解决问题的方法 Ubuntu操作问题 vi编辑方向键键盘乱码回退键不能使用的问题 编辑/etc/systemd/resolved.conf文件来修改DNS&#xff0c;结果编辑时键盘乱码&#xff0c;按下方向键会出现ABCD&#xff0c;且回退键…...

汽车发动机系统(ems)详细解析

汽车发动机系统EMS&#xff0c;即Engine-Management-System&#xff08;发动机管理系统&#xff09;&#xff0c;是现代汽车电子控制技术的重要组成部分。以下是对汽车发动机系统EMS的详细解析&#xff0c;内容将涵盖其定义、工作原理、主要组成、功能特点、技术发展以及市场应…...

对比学习训练是如何进行的

对比学习&#xff08;Contrastive Learning&#xff09;是一种自监督学习的方法&#xff0c;旨在通过拉近相似样本的表示、拉远不相似样本的表示来学习特征表示。在训练过程中&#xff0c;模型并不依赖标签&#xff0c;而是通过样本之间的相似性进行学习。以下是对比学习的基本…...

React 生命周期 - useEffect 介绍

在 React 中&#xff0c;useEffect 钩子可以被看作是函数组件中的一种副作用管理工具&#xff0c;它的行为可以模拟类组件中的不同生命周期方法。useEffect 的执行时机取决于其依赖项数组&#xff08;第二个参数&#xff09;的设置方式。 根据 useEffect 的使用方式&#xff0c…...

OpenCV-指纹识别

文章目录 一、意义二、代码实现1.计算匹配点2.获取编号3.获取姓名4.主函数 三、总结 一、意义 使用OpenCV进行指纹识别是一个复杂且挑战性的任务&#xff0c;因为指纹识别通常需要高精度的特征提取和匹配算法。虽然OpenCV提供了多种图像处理和计算机视觉的工具&#xff0c;但直…...

Python爬虫实战:研究MechanicalSoup库相关技术

一、MechanicalSoup 库概述 1.1 库简介 MechanicalSoup 是一个 Python 库,专为自动化交互网站而设计。它结合了 requests 的 HTTP 请求能力和 BeautifulSoup 的 HTML 解析能力,提供了直观的 API,让我们可以像人类用户一样浏览网页、填写表单和提交请求。 1.2 主要功能特点…...

idea大量爆红问题解决

问题描述 在学习和工作中&#xff0c;idea是程序员不可缺少的一个工具&#xff0c;但是突然在有些时候就会出现大量爆红的问题&#xff0c;发现无法跳转&#xff0c;无论是关机重启或者是替换root都无法解决 就是如上所展示的问题&#xff0c;但是程序依然可以启动。 问题解决…...

【Redis技术进阶之路】「原理分析系列开篇」分析客户端和服务端网络诵信交互实现(服务端执行命令请求的过程 - 初始化服务器)

服务端执行命令请求的过程 【专栏简介】【技术大纲】【专栏目标】【目标人群】1. Redis爱好者与社区成员2. 后端开发和系统架构师3. 计算机专业的本科生及研究生 初始化服务器1. 初始化服务器状态结构初始化RedisServer变量 2. 加载相关系统配置和用户配置参数定制化配置参数案…...

Java多线程实现之Callable接口深度解析

Java多线程实现之Callable接口深度解析 一、Callable接口概述1.1 接口定义1.2 与Runnable接口的对比1.3 Future接口与FutureTask类 二、Callable接口的基本使用方法2.1 传统方式实现Callable接口2.2 使用Lambda表达式简化Callable实现2.3 使用FutureTask类执行Callable任务 三、…...

在Ubuntu中设置开机自动运行(sudo)指令的指南

在Ubuntu系统中&#xff0c;有时需要在系统启动时自动执行某些命令&#xff0c;特别是需要 sudo权限的指令。为了实现这一功能&#xff0c;可以使用多种方法&#xff0c;包括编写Systemd服务、配置 rc.local文件或使用 cron任务计划。本文将详细介绍这些方法&#xff0c;并提供…...

自然语言处理——Transformer

自然语言处理——Transformer 自注意力机制多头注意力机制Transformer 虽然循环神经网络可以对具有序列特性的数据非常有效&#xff0c;它能挖掘数据中的时序信息以及语义信息&#xff0c;但是它有一个很大的缺陷——很难并行化。 我们可以考虑用CNN来替代RNN&#xff0c;但是…...

优选算法第十二讲:队列 + 宽搜 优先级队列

优选算法第十二讲&#xff1a;队列 宽搜 && 优先级队列 1.N叉树的层序遍历2.二叉树的锯齿型层序遍历3.二叉树最大宽度4.在每个树行中找最大值5.优先级队列 -- 最后一块石头的重量6.数据流中的第K大元素7.前K个高频单词8.数据流的中位数 1.N叉树的层序遍历 2.二叉树的锯…...

Mac下Android Studio扫描根目录卡死问题记录

环境信息 操作系统: macOS 15.5 (Apple M2芯片)Android Studio版本: Meerkat Feature Drop | 2024.3.2 Patch 1 (Build #AI-243.26053.27.2432.13536105, 2025年5月22日构建) 问题现象 在项目开发过程中&#xff0c;提示一个依赖外部头文件的cpp源文件需要同步&#xff0c;点…...

[ACTF2020 新生赛]Include 1(php://filter伪协议)

题目 做法 启动靶机&#xff0c;点进去 点进去 查看URL&#xff0c;有 ?fileflag.php说明存在文件包含&#xff0c;原理是php://filter 协议 当它与包含函数结合时&#xff0c;php://filter流会被当作php文件执行。 用php://filter加编码&#xff0c;能让PHP把文件内容…...

论文阅读笔记——Muffin: Testing Deep Learning Libraries via Neural Architecture Fuzzing

Muffin 论文 现有方法 CRADLE 和 LEMON&#xff0c;依赖模型推理阶段输出进行差分测试&#xff0c;但在训练阶段是不可行的&#xff0c;因为训练阶段直到最后才有固定输出&#xff0c;中间过程是不断变化的。API 库覆盖低&#xff0c;因为各个 API 都是在各种具体场景下使用。…...