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

移情别恋c++ ദ്ദി˶ー̀֊ー́ ) ——6.vector(无习题)

C++ 中的 vector 容器详细总结

1. 什么是 vector

vector 是 C++ 标准模板库 (STL) 中的一种动态数组容器。它的底层实现是一个可以自动扩展的数组,支持随机访问和动态调整大小,是 C++ 中最常用的序列容器之一。vector 在插入、删除、遍历以及随机访问等方面有着优异的表现,尤其是在数据需要频繁随机访问且不会频繁在中间位置进行插入或删除操作的场景中表现非常出色。

1.1 动态数组的特点

vector 是动态数组,意味着它的大小在程序运行过程中可以根据需要自动扩展。当需要添加新元素且当前容量不足时,vector 会分配更大的内存空间,并将原有的数据拷贝到新的内存中。这种动态性使得 vector 在数据存储和处理上非常灵活,但也会带来一些性能上的开销。

2. vector 的特点与优缺点

2.1 vector 的特点

  • 动态大小vector 的大小可以根据需要自动扩展或缩小,用户无需手动管理内存。
  • 连续内存存储vector 使用连续的内存块存储数据,类似于数组,这使得它支持 O(1) 时间复杂度的随机访问。
  • 高效的尾部操作vector 在尾部添加或删除元素的时间复杂度为摊销 O(1)。
  • 支持迭代器vector 提供随机访问迭代器,可以方便地遍历和操作数据。

2.2 vector 的优点

  • 随机访问效率高:由于 vector 的元素在内存中是连续存储的,因此可以使用下标直接访问元素,时间复杂度为 O(1),访问效率非常高。
  • 动态扩展vector 会根据元素的增加自动扩展容量,用户无需关心内存管理问题。
  • 支持 STL 算法vector 支持与 STL 算法直接配合使用,拥有良好的可扩展性和通用性。

2.3 vector 的缺点

  • 插入和删除操作的性能问题:在 vector 中间位置插入或删除元素需要移动后续所有元素,因此时间复杂度为 O(n),效率较低。
  • 内存重新分配开销:当 vector 的容量不足时,需要重新分配更大的内存并拷贝原有数据,这会带来额外的性能开销。
  • 内存浪费:为了减少频繁的内存分配,vector 通常会预留比当前需要更多的内存空间,这可能会导致一定程度的内存浪费。

3. vector 的常用操作与函数

3.1 创建与初始化

vector 可以通过多种方式进行创建和初始化,以下是一些常见的方式:

#include <vector>
#include <iostream>int main() {std::vector<int> vec1;                    // 创建空的 vectorstd::vector<int> vec2(10);                 // 创建包含 10 个元素的 vector,默认值为 0std::vector<int> vec3(10, 5);              // 创建包含 10 个元素的 vector,值为 5std::vector<int> vec4 = {1, 2, 3, 4};      // 使用列表初始化std::vector<int> vec5(vec4.begin(), vec4.end()); // 使用其他容器的迭代器进行初始化return 0;
}

3.2 增加元素

  • push_back(value):在 vector 的末尾添加一个元素。
vec1.push_back(10);  // 在末尾添加 10
  • emplace_back(args...):在末尾原地构造元素,避免不必要的拷贝。
vec1.emplace_back(20);  // 原地构造 20

3.3 删除元素

  • pop_back():删除 vector 末尾的元素。
vec1.pop_back();  // 删除末尾元素
  • erase(iterator):删除指定位置的元素。
vec1.erase(vec1.begin() + 1);  // 删除第二个元素
  • clear():清空 vector 中所有元素。
vec1.clear();  // 清空容器

3.4 访问元素

  • 使用下标访问
int value = vec1[2];  // 获取第三个元素
  • 使用 at(index) 方法访问,带越界检查:
int value = vec1.at(2);  // 获取第三个元素
  • 获取第一个和最后一个元素
int first = vec1.front();
int last = vec1.back();

3.5 迭代器的使用

  • begin(), end():获取指向第一个元素和末尾后一个位置的迭代器。
for (auto it = vec1.begin(); it != vec1.end(); ++it) {std::cout << *it << " ";
}
  • rbegin(), rend():获取反向迭代器,遍历元素时从尾部开始。
for (auto rit = vec1.rbegin(); rit != vec1.rend(); ++rit) {std::cout << *rit << " ";
}

3.6 容量相关函数

  • size():获取当前元素的数量。
  • capacity():获取当前分配的存储空间,可以存储的元素数量。
  • resize(new_size):改变 vector 的大小。
  • reserve(new_capacity):预分配存储空间,减少内存重新分配的开销。
  • shrink_to_fit():将 capacity 缩小到与 size 相同,减少内存占用。
std::cout << "Size: " << vec1.size() << "\n";
std::cout << "Capacity: " << vec1.capacity() << "\n";
vec1.reserve(20);  // 预分配 20 个元素的空间

4. vector 的内部机制与性能分析

4.1 自动扩展机制

当向 vector 中添加元素时,如果当前容量不足,vector 会自动分配新的更大的内存空间。一般来说,每次扩展会使容量翻倍,以减少扩展次数,从而提高效率。这也意味着在一些场景中,尽可能使用 reserve() 方法来预分配内存,以避免频繁的内存重新分配。

4.2 内存管理与重新分配

vector 在容量不足时会分配更大的内存,并将原有的数据拷贝到新分配的内存中,这个过程称为重新分配(reallocation)。重新分配会带来以下几点开销:

  • 内存分配开销:分配新的内存空间需要系统调用,可能会引入一定的开销。
  • 数据拷贝开销:每次重新分配时,所有元素都需要从旧内存复制到新内存,这在数据量较大时会带来较高的性能消耗。
  • 频繁分配导致的内存碎片:频繁的内存重新分配可能导致内存碎片的增加,影响内存的整体利用效率。

因此,对于已经知道大致数据量的场景,推荐使用 reserve() 来预先分配足够的空间,减少内存重新分配的次数。

4.3 随机访问的特性

由于 vector 的底层实现是一个连续数组,因此它支持 O(1) 时间复杂度的随机访问。这一点使得 vector 相较于其他序列容器(如 list)在需要频繁随机访问时更加高效。尤其是在需要通过下标快速定位特定元素的场景下,vector 是一个非常好的选择。

4.4 vector 的增长策略

C++ 标准中并未规定 vector 的具体增长策略,但大多数实现中,vector 会在容量不足时将容量翻倍。这种指数级增长的策略可以确保在插入元素时具有摊销的常数时间复杂度,从而在大多数情况下提供良好的性能。

5. vector 的高级操作

5.1 插入与删除

  • insert(iterator, value):在指定位置插入一个元素。
vec1.insert(vec1.begin() + 2, 15);  // 在第三个位置插入 15
  • insert(iterator, count, value):在指定位置插入多个相同的元素。
vec1.insert(vec1.begin(), 3, 5);  // 在开头插入三个值为 5 的元素
  • erase(iterator):删除指定位置的元素。
vec1.erase(vec1.begin() + 1);  // 删除第二个元素
  • erase(iterator_first, iterator_last):删除指定范围内的元素。
vec1.erase(vec1.begin(), vec1.begin() + 3);  // 删除前三个元素

5.2 交换与赋值

  • swap(other_vector):交换两个 vector 的内容。
std::vector<int> vec2 = {10, 20, 30};
vec1.swap(vec2);  // 交换 vec1 和 vec2 的内容
  • assign(count, value):将 vector 的内容替换为指定数量的相同元素。
vec1.assign(5, 100);  // 用 5 个值为 100 的元素替换原内容
  • assign(iterator_first, iterator_last):使用指定范围内的元素替换 vector 的内容。
vec1.assign(vec2.begin(), vec2.end());  // 用 vec2 的所有元素替换 vec1 的内容

6. vector 的应用场景与性能优化

6.1 适用场景

  • 频繁随机访问vector 支持 O(1) 的随机访问,因此适合需要频繁通过下标访问元素的场景。
  • 数据量动态变化vector 的大小可以动态扩展,适用于数据量不固定且需要动态添加元素的场景。
  • 相对较少的插入和删除操作:如果主要在末尾进行插入和删除,vector 的性能非常好,但在中间位置频繁插入或删除元素时,性能较差。

6.2 性能优化建议

  • 预分配内存:如果知道大致的数据量,可以使用 reserve() 预先分配内存,以减少扩展带来的重新分配开销。
  • 减少不必要的复制:在添加元素时,尽量使用 emplace_back() 而不是 push_back(),这样可以避免不必要的对象复制。
  • 使用移动语义:当元素支持移动语义时,vector 会优先使用移动操作来减少复制开销,尽量使用支持移动语义的类型。

7. vector 与其他容器的对比

7.1 与 list 的对比

  • 存储结构vector 使用连续内存存储,支持 O(1) 时间复杂度的随机访问;list 使用链表存储,不支持随机访问。
  • 插入和删除操作vector 在末尾插入和删除的效率较高,但在中间位置插入和删除需要移动大量元素,时间复杂度为 O(n)。list 的插入和删除操作在任何位置都是 O(1)。
  • 内存使用vector 的内存使用更加紧凑,而 list 由于存储了前驱和后继指针,内存占用更大。
  • 遍历性能vector 的连续内存使得遍历性能更好,能够更好地利用 CPU 缓存,而 list 的遍历性能相对较差。

7.2 与 deque 的对比

  • 存储结构deque(双端队列)由多个连续内存块组成,支持快速的头尾插入和删除操作,而 vector 是单个连续内存块。
  • 访问性能vector 支持 O(1) 时间复杂度的随机访问,deque 也支持随机访问,但性能稍逊于 vector
  • 插入和删除操作deque 在头尾的插入和删除效率高,而 vector 只在尾部插入和删除效率较高。

7.3 与 array 的对比

  • 大小固定array 是大小固定的容器,在编译时确定大小,vector 是动态大小的容器,能够根据需要自动扩展。
  • 性能比较array 的性能优于 vector,因为它没有动态扩展的开销。对于大小固定且不需要动态调整的场景,array 是更好的选择。

8. 示例代码

下面是一个完整的示例代码,展示了 vector 的常用操作以及高级功能:

#include <iostream>
#include <vector>int main() {// 创建 vector 并初始化std::vector<int> vec = {1, 2, 3, 4, 5};// 添加元素vec.push_back(6);   // 在末尾添加元素vec.emplace_back(7);  // 原地构造元素// 遍历 vectorstd::cout << "Elements: ";for (int val : vec) {std::cout << val << " ";}std::cout << std::endl;// 删除元素vec.pop_back();    // 删除末尾元素vec.erase(vec.begin() + 1);  // 删除第二个元素// 查看大小和容量std::cout << "Size: " << vec.size() << ", Capacity: " << vec.capacity() << std::endl;// 预分配空间vec.reserve(20);std::cout << "Capacity after reserve: " << vec.capacity() << std::endl;// 清空 vectorvec.clear();std::cout << "Size after clear: " << vec.size() << std::endl;return 0;
}

9. 总结

vector 是 C++ 中非常强大且常用的容器,适用于需要动态大小且具有随机访问需求的场景。它提供了丰富的操作接口,并且通过连续的内存布局提供了较高的访问效率。然而,在涉及频繁插入和删除操作时,特别是在中间位置的操作,vector 的性能可能会受到限制。合理选择合适的容器以匹配具体的应用场景非常重要,例如在需要频繁插入和删除的场景中可以选择 list,在需要快速访问头尾元素的场景中可以选择 deque。对于大多数应用场景,vector 是一个高效且灵活的选择,能够满足大多数序列数据的处理需求。

相关文章:

移情别恋c++ ദ്ദി˶ー̀֊ー́ ) ——6.vector(无习题)

C 中的 vector 容器详细总结 1. 什么是 vector&#xff1f; vector 是 C 标准模板库 (STL) 中的一种动态数组容器。它的底层实现是一个可以自动扩展的数组&#xff0c;支持随机访问和动态调整大小&#xff0c;是 C 中最常用的序列容器之一。vector 在插入、删除、遍历以及随机…...

SpringBoot技术支持的桂林景点导航

2相关技术 2.1 MYSQL数据库 MySQL是一个真正的多用户、多线程SQL数据库服务器。 是基于SQL的客户/服务器模式的关系数据库管理系统&#xff0c;它的有点有有功能强大、使用简单、管理方便、安全可靠性高、运行速度快、多线程、跨平台性、完全网络化、稳定性等&#xff0c;非常…...

利用vmware在移动硬盘安装Ubuntu2go

安装 买个移动硬盘&#xff0c;usb插电脑&#xff0c;磁盘管理看磁盘序列号 vmware新建虚拟机 这一步选择磁盘管理里面看到的磁盘4 先不要开机&#xff0c;选择设置里面UEFI 和安装正常Ubuntu一致操作即可&#xff0c;这里可以不选高级&#xff0c;默认一个引导分区&…...

Spring Boot:中小型医院网站的敏捷开发

摘 要 本基于Spring Boot的中小型医院网站设计目标是实现用户网络预约挂号的功能&#xff0c;同时提高医院管理效率&#xff0c;更好的为广大用户服务。 本文重点阐述了中小型医院网站的开发过程&#xff0c;以实际运用为开发背景&#xff0c;基于Spring Boot框架&#xff0c;运…...

241011-在jupyter中实现文件夹压缩后下载

241011-在jupyter中实现文件夹压缩后下载 在使用jupyter notebook过程中&#xff0c;我们经常会遇到成堆的文件无法批量下载的问题&#xff0c;这里提供压缩文件夹代码&#xff0c;压缩后即可右键文件选择download实现批量下载 import zipfile import os# 设置你想要压缩的文…...

.NET 一款用于转储指定进程内存的工具

01阅读须知 此文所提供的信息只为网络安全人员对自己所负责的网站、服务器等&#xff08;包括但不限于&#xff09;进行检测或维护参考&#xff0c;未经授权请勿利用文章中的技术资料对任何计算机系统进行入侵操作。利用此文所提供的信息而造成的直接或间接后果和损失&#xf…...

Splunk 修补关键漏洞,包括远程代码执行漏洞

领先的数据分析和安全监控平台 Splunk 发布了一系列安全更新&#xff0c;以解决 Splunk Enterprise 和 Splunk Cloud Platform 中的多个漏洞。这些漏洞的严重程度不一&#xff0c;有些可实现远程代码执行&#xff08;RCE&#xff09;&#xff0c;有些则允许低权限用户访问敏感信…...

搭建一个vue3+vite框架

可以使用以下两种搭建方式 通过create-vue搭建vue3 项目&#xff08;建议使用&#xff09; create-vue create-vue 是 Vue.js 官方推荐的用于快速启动 Vite 驱动的 Vue 项目的脚手架工具。它简化了创建新 Vue 项目的过程&#xff0c;提供了预配置的项目结构&#xff0c;并集…...

【含文档】基于Springboot+Vue的公交管理系统(含源码+数据库+lw)

1.开发环境 开发系统:Windows10/11 架构模式:MVC/前后端分离 JDK版本: Java JDK1.8 开发工具:IDEA 数据库版本: mysql5.7或8.0 数据库可视化工具: navicat 服务器: SpringBoot自带 apache tomcat 主要技术: Java,Springboot,mybatis,mysql,vue 2.视频演示地址 3.功能 系统定…...

自闭症儿童能否适应学校生活:提供专业辅助,助力顺利融入

自闭症&#xff0c;这一复杂的神经发育障碍&#xff0c;往往让许多家庭在孩子的教育问题上倍感焦虑。面对即将步入学校生活的自闭症儿童&#xff0c;家长们不禁要问&#xff1a;他们能否适应学校生活&#xff1f;如何帮助他们顺利融入&#xff1f;幸运的是&#xff0c;随着医疗…...

MQTTnet.Server同时支持mqtt及websocket协议

Net6后写法 Net6前写法 Program.cs using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Hosting; using MQTTnet.AspNetCore; using System; using System.IO;namespace MQTTnet.Server {public class Program{publ…...

【数据结构】二叉树(一)遍历

导言 前面以及有了堆的基础&#xff0c;现在来学习二叉树。二叉树的学习和前面的数据结构很不一样&#xff0c;前面我们主要学习用数据结构储存数据&#xff0c;以及实际手搓数据结构的增删查改&#xff1b;而学习二叉树主要是为我们以后学搜索二叉树以及后面的AVL树等数据结构…...

【C++ 贪心】1616. 分割两个字符串得到回文串|1868

本文涉及知识点 C贪心 LeetCode1616. 分割两个字符串得到回文串 给你两个字符串 a 和 b &#xff0c;它们长度相同。请你选择一个下标&#xff0c;将两个字符串都在 相同的下标 分割开。由 a 可以得到两个字符串&#xff1a; aprefix 和 asuffix &#xff0c;满足 a aprefi…...

识别秒拨风险的具体方法及策略

秒拨技术是利用家用宽带拨号上网&#xff08;PPPoE&#xff09;的特性&#xff0c;通过频繁断线重连来获取新的IP地址&#xff0c;从而构建代理服务或进行其他网络活动。这种技术使得IP地址的切换频率极高&#xff0c;加大了识别和追踪的难度。因此&#xff0c;首先需要对秒拨技…...

[Python]如何在Ubuntu中建置python venv虛擬環境,並安裝TensorFlow和OpenCV函式庫?

為了在樹莓派上實現物件影像辨識功能&#xff0c;同時不影響樹莓派原來的python運行環境&#xff0c;選擇建置python虛擬環境[Note1]是一個好方式&#xff0c;其可避免版本衝突和不同運行環境的問題。另外&#xff0c;一併在該虛擬環境中安裝TensorFlow[Note2]和OpenCV[Note3]等…...

Excel:Cells(Rows.Count, 1).End(xlUp).Row和Cells(Rows.Count, 1).End(xlUp)有什么区别

Cells(Rows.Count, 1).End(xlUp).Row 和 Cells(Rows.Count, 1).End(xlUp) 是 VBA 中用于定位 Excel 工作表中单元格的两种不同用法。以下是它们的区别&#xff1a; 1. Cells(Rows.Count, 1).End(xlUp).Row 功能: 这个表达式返回的是一个行号&#xff08;Long 类型&#xff09…...

E. Count Paths

题目 题解&#xff1a; #include <bits/stdc.h>#define forn(i, n) for (int i 0; i < int(n); i)using namespace std;int n; vector<int> a; vector<vector<int>> g;long long ans; vector<map<int, int>> cnt;void dfs(int v, int …...

集合论(ZFC)之良创关系(Well-Founded Relation)

定义在集合S中的一个二元关系&#xff08;Binary Relation&#xff09;记&#xff0c;<&#xff0c;有&#xff08;S&#xff0c;<&#xff09;。如果对于集合S的任意非空子集&#xff0c;都存在关系&#xff08;<&#xff09;下的最小元素&#xff0c;那么该关系&…...

centos 安装达梦数据库

一、环境准备 1.1、确认操作系统的版本和数据库的版本是否一致 ## 查看系统版本&#xff1a;cat /etc/redhat-release CentOS Linux release 7.5.1804 (Core)1.2、关闭防火墙和Selinux # 查看selinux是不是disabled / enforce cat /etc/selinux/config## 查看防火墙状态 fir…...

《Windows PE》6.4.1 无 DLL远程注入

本节我们将演示如何实现远程注入的两种不同方案。方案一选择远程注入代码和数据&#xff0c;方案二选择远程注入DLL。 本节必须掌握的知识点&#xff1a; 无DLL远程注入 远程注入DLL 6.4.1 无DLL远程注入 实验四十五&#xff1a;无DLL远程注入&#xff08;C语言实现&#xf…...

Flask RESTful 示例

目录 1. 环境准备2. 安装依赖3. 修改main.py4. 运行应用5. API使用示例获取所有任务获取单个任务创建新任务更新任务删除任务 中文乱码问题&#xff1a; 下面创建一个简单的Flask RESTful API示例。首先&#xff0c;我们需要创建环境&#xff0c;安装必要的依赖&#xff0c;然后…...

在HarmonyOS ArkTS ArkUI-X 5.0及以上版本中,手势开发全攻略:

在 HarmonyOS 应用开发中&#xff0c;手势交互是连接用户与设备的核心纽带。ArkTS 框架提供了丰富的手势处理能力&#xff0c;既支持点击、长按、拖拽等基础单一手势的精细控制&#xff0c;也能通过多种绑定策略解决父子组件的手势竞争问题。本文将结合官方开发文档&#xff0c…...

【单片机期末】单片机系统设计

主要内容&#xff1a;系统状态机&#xff0c;系统时基&#xff0c;系统需求分析&#xff0c;系统构建&#xff0c;系统状态流图 一、题目要求 二、绘制系统状态流图 题目&#xff1a;根据上述描述绘制系统状态流图&#xff0c;注明状态转移条件及方向。 三、利用定时器产生时…...

WordPress插件:AI多语言写作与智能配图、免费AI模型、SEO文章生成

厌倦手动写WordPress文章&#xff1f;AI自动生成&#xff0c;效率提升10倍&#xff01; 支持多语言、自动配图、定时发布&#xff0c;让内容创作更轻松&#xff01; AI内容生成 → 不想每天写文章&#xff1f;AI一键生成高质量内容&#xff01;多语言支持 → 跨境电商必备&am…...

PAN/FPN

import torch import torch.nn as nn import torch.nn.functional as F import mathclass LowResQueryHighResKVAttention(nn.Module):"""方案 1: 低分辨率特征 (Query) 查询高分辨率特征 (Key, Value).输出分辨率与低分辨率输入相同。"""def __…...

【Linux】Linux 系统默认的目录及作用说明

博主介绍&#xff1a;✌全网粉丝23W&#xff0c;CSDN博客专家、Java领域优质创作者&#xff0c;掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域✌ 技术范围&#xff1a;SpringBoot、SpringCloud、Vue、SSM、HTML、Nodejs、Python、MySQL、PostgreSQL、大数据、物…...

根目录0xa0属性对应的Ntfs!_SCB中的FileObject是什么时候被建立的----NTFS源代码分析--重要

根目录0xa0属性对应的Ntfs!_SCB中的FileObject是什么时候被建立的 第一部分&#xff1a; 0: kd> g Breakpoint 9 hit Ntfs!ReadIndexBuffer: f7173886 55 push ebp 0: kd> kc # 00 Ntfs!ReadIndexBuffer 01 Ntfs!FindFirstIndexEntry 02 Ntfs!NtfsUpda…...

掌握 HTTP 请求:理解 cURL GET 语法

cURL 是一个强大的命令行工具&#xff0c;用于发送 HTTP 请求和与 Web 服务器交互。在 Web 开发和测试中&#xff0c;cURL 经常用于发送 GET 请求来获取服务器资源。本文将详细介绍 cURL GET 请求的语法和使用方法。 一、cURL 基本概念 cURL 是 "Client URL" 的缩写…...

ubuntu22.04有线网络无法连接,图标也没了

今天突然无法有线网络无法连接任何设备&#xff0c;并且图标都没了 错误案例 往上一顿搜索&#xff0c;试了很多博客都不行&#xff0c;比如 Ubuntu22.04右上角网络图标消失 最后解决的办法 下载网卡驱动&#xff0c;重新安装 操作步骤 查看自己网卡的型号 lspci | gre…...

保姆级【快数学会Android端“动画“】+ 实现补间动画和逐帧动画!!!

目录 补间动画 1.创建资源文件夹 2.设置文件夹类型 3.创建.xml文件 4.样式设计 5.动画设置 6.动画的实现 内容拓展 7.在原基础上继续添加.xml文件 8.xml代码编写 (1)rotate_anim (2)scale_anim (3)translate_anim 9.MainActivity.java代码汇总 10.效果展示 逐帧…...