std : : vector

news2025/1/19 22:29:59

一.简介

std::vector 的底层实现通常基于动态数组(dynamic array),它是一种连续分配的内存块,允许元素的快速随机访问。下面是 std::vector 的一些关键特点和底层实现细节:

  1. 连续内存块std::vector 内部使用一块连续的内存块来存储其元素,这使得元素的随机访问非常高效,因为可以通过指针算术运算来访问元素。

  2. 动态大小std::vector 允许动态地增加或减少其大小。当元素数量达到内部分配的容量时,std::vector 会重新分配更大的内存块,并将元素复制到新的内存块中。这种自动内存管理使得向量的大小可以根据需要进行调整,而不需要手动管理内存。

  3. 容量和大小std::vector 有两个重要的属性,即容量(capacity)和大小(size)。

    • 容量是 std::vector 当前内部分配的内存块的大小,通常大于或等于大小。当向量的大小超过容量时,会触发内存重新分配,容量会增加。
    • 大小是 std::vector 中实际存储的元素数量。
  4. 动态内存分配std::vector 使用 newdelete 运算符(或 mallocfree 函数,取决于具体实现)来动态分配和释放内存。当需要重新分配内存时,它会为新的内存块分配内存,然后将元素从旧的内存块复制到新的内存块,最后释放旧内存。

  5. 异常安全std::vector 的实现通常会提供异常安全性,这意味着如果在内存重新分配过程中发生异常,不会导致数据丢失或内存泄漏。这是通过使用临时副本和交换技术来实现的。

  6. 迭代器std::vector 提供了迭代器(iterator)来遍历元素,迭代器通常是指针的封装,可以用于访问 std::vector 中的元素。

  7. 内存效率:由于 std::vector 的元素存储在连续的内存块中,它在内存访问上具有很好的局部性,这有助于提高内存访问效率。

总之,std::vector 是一个非常灵活和高效的容器,它提供了动态数组的功能,使得元素的访问和管理变得非常方便。虽然 std::vector 的大小可以动态增长,但由于内存重新分配的开销,如果需要频繁插入或删除元素,可能需要考虑其他容器类型,如 std::liststd::deque,它们可以更高效地支持插入和删除操作。

扩展:

动态数组(Dynamic Array)是一种数据结构,它是一个连续分配的内存块,用于存储具有相同数据类型的元素。动态数组的大小可以动态增长或缩小,以适应元素的插入和删除操作。

以下是动态数组的主要特点和操作:

  1. 连续内存块:动态数组的元素存储在一块连续的内存块中,这意味着元素的地址在内存中是连续的,这有助于快速随机访问元素。通过索引访问元素的时间复杂度是 O(1)。

  2. 动态大小:动态数组允许在运行时动态增加或减少其大小。这意味着您可以向数组中添加元素或从数组中删除元素,而不需要预先知道数组的大小。这种动态大小的特性使得动态数组非常灵活。

  3. 内存分配:当向动态数组添加元素并且没有足够的内存容量时,动态数组会自动分配更大的内存块,将现有元素复制到新的内存块中,并释放旧的内存块。这个过程称为重新分配(re-allocation)。

  4. 时间复杂度:动态数组的插入和删除操作的时间复杂度取决于插入或删除的位置。在末尾进行插入和删除操作通常是最高效的,时间复杂度为 O(1),因为不需要移动元素。在数组中间进行插入或删除操作可能需要移动后续元素,时间复杂度为 O(n)。

  5. 容量和大小:动态数组具有容量(capacity)和大小(size)两个重要属性。

    • 容量是动态数组内部分配的内存块的大小,通常大于或等于大小。
    • 大小是动态数组中实际存储的元素数量。
  6. 迭代器:动态数组通常提供迭代器(iterator),可以用于遍历数组中的元素。

动态数组是一种非常常见和有用的数据结构,它具有灵活性和高效性的优点。

二.运用场景

std::vector 是 C++ 标准库提供的一个动态数组容器,它在许多不同的场景中都非常有用。以下是一些常见的 std::vector 的运用场景:

  1. 动态数组std::vector 是一种动态数组,它可以根据需要自动增加或减少大小。这使得它成为存储不确定数量元素的首选选择,而不需要预先知道数组的大小

  2. 数据收集std::vector 适用于收集大量数据,例如从文件、网络或用户输入中读取的数据。您可以使用 push_back() 方法轻松添加新数据。

  3. 容器替代std::vector 可以替代 C 数组,因为它提供了更多的功能和安全性。与 C 数组不同,std::vector 知道自己的大小,而且可以动态调整大小。

  4. 迭代访问:如果需要通过索引或迭代器访问元素,并且需要快速随机访问能力std::vector 是一个很好的选择。它的时间复杂度为 O(1)。

  5. 栈和队列:虽然 std::vector 主要设计用于随机访问,但它也可以用作栈(先进后出)或队列(先进先出)。使用 push_back()pop_back() 方法可以将其用作栈,而使用 push_back()erase() 可以将其用作队列。

  6. 算法和数据处理std::vector 与标准库中的各种算法结合使用,可以用于各种数据处理任务,例如排序、查找、筛选、转换等。

  7. 高性能计算:在需要高性能的数值计算领域,std::vector 通常用于存储大量数值数据,例如图形处理、科学计算、模拟等。

  8. 游戏开发:在游戏开发中,std::vector 常用于存储游戏对象、粒子、动画帧等

  9. 数据传输std::vector 可以用于数据传输,例如从文件读取数据到向量,然后将向量传递给其他处理模块。

需要注意的是,虽然 std::vector 在许多情况下非常有用,但在某些特定情况下,其他容器类型(例如 std::liststd::dequestd::setstd::map 等)可能更适合特定的数据结构和操作。因此,在选择容器类型时,需要根据具体的需求和性能要求进行权衡和选择。

三.写个比较器

方法一:直接静态函数
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
static bool cmp(const pair<int, int>& a, const pair<int, int>& b) {
    if (a.first == b.first) return a.second < b.second;
    return a.first < b.first;
}
void display(vector<pair<int,int>>ans) { for (auto it : ans) cout << it.first << " " << it.second<<"\t"; }
int main() {
    vector<pair<int, int>>ans = { {1,2},{5,3},{2,5},{2,1},{7,2} };
    display(ans);
    cout << endl;
    sort(ans.begin(), ans .end(), cmp);
    display(ans);
    return 0;
}

 

方法二:写入结构体
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
struct cmp {
    bool operator()(const pair<int,int>&a,const pair<int,int>&b) {
        if (a.first == b.first) return a.second < b.second;
        return a.first < b.first;
    }
};
void display(vector<pair<int,int>>ans) { for (auto it : ans) cout << it.first << " " << it.second<<"\t"; }
int main() {
    vector<pair<int, int>>ans = { {1,2},{5,3},{2,5},{2,1},{7,2} };
    display(ans);
    sort(ans.begin(), ans .end(), cmp());
    cout << "----------" << endl;
    display(ans);
    return 0;
}

         在使用的时候,cmp() 表示实例化对象,要是不想实例化对象怎么办呢?这个时候我们可以把比较操作定义成静态成员函数,这样就可以通过这个结构体的名称来调用这个函数,而不需要实例化对象。

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
struct numcmp {
    static bool cmp(const pair<int, int>& a, const pair<int, int>& b) {
        if (a.first == b.first) return a.second < b.second;
        return a.first < b.first;
    }
};
void display(vector<pair<int,int>>ans) { for (auto it : ans) cout << it.first << " " << it.second<<"\t"; }
int main() {
    vector<pair<int, int>>ans = { {1,2},{5,3},{2,5},{2,1},{7,2} };
    display(ans);
    cout << endl;
    sort(ans.begin(), ans .end(), numcmp::cmp);
    display(ans);
    return 0;
}

 

区别:

这两种写法在功能上是等效的,它们都可以用于自定义比较操作,以对pair或其他数据结构进行排序。然而,它们之间有一些细微的区别和优劣势:

  1. 可读性:使用函数指针或函数对象(结构体中的operator())来定义比较操作,通常更易于理解和阅读。函数名可以明确指示比较的目的,而不需要查看结构体的成员。

  2. 灵活性:将比较操作封装在结构体中(函数对象方式)通常更灵活,因为你可以在结构体中存储额外的状态或配置,以影响比较的行为。这对于实现不同的排序方式很有用。

  3. 命名冲突:如果你有多个不同的比较操作,并且它们需要在不同的上下文中使用,将它们放入结构体中可以避免函数名冲突的问题,因为每个结构体都有自己的作用域。函数指针方式可能需要更多的命名空间管理。

  4. 语法:函数指针方式更紧凑,但在语法上可能略显繁琐。函数对象方式需要创建一个结构体并在排序函数中使用括号运算符来调用,这可能看起来有点冗长。

总的来说,选择哪种方式取决于你的需求和个人偏好。如果你只需要一个简单的比较操作,函数指针可能更合适。但如果你需要更复杂的比较逻辑,或者希望更好地组织和封装比较操作,那么使用函数对象(结构体中的operator())可能更好。

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

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

相关文章

【Unity的HDRP下ShaderGraph实现权重缩放全息投影_(内附源码)】

实现权重缩放全息投影 效果如下 效果如下 顶点位置偏移 链接&#xff1a; 提取码&#xff1a;1234

NtripShare Cloud GNSS解算云平台之动态、快速静态、静态解算

过去半年以来基本精力都在测量机器人自动化监测领域&#xff0c;相对GNSS平台本身除了进行逻辑更新之外&#xff0c;算法层面基本没尽兴大的改动&#xff0c;目前NtripShare Cloud V3版本中支持三种解算方式&#xff0c;即动态、快速静态、静态。 1、动态---RTK算法&#xff0…

C++:vector

目录 一、关于vector 二、vector的相关函数 三、相关函数的使用 ①构造函数 ②size ③[] ​编辑 ④push_back ⑤迭代器iterator ⑥reserve ⑦resize ⑧find ⑨insert ⑩erase ⑪sort 一、关于vector vector比较像数组 观察可知&#xff0c;vector有两个模板参数…

使用Linux下的MySQL数据库

PS&#xff1a;文章最后有“开心一刻”&#xff0c;记得看哦&#xff0c;给生活增加点儿趣味。 大家好&#xff0c;我是Linux持续学习者。在本文中&#xff0c;我们将介绍如何在Linux系统下安装、配置和使用MySQL数据库。MySQL是一款使用最广泛的开源关系型数据库管理系统&…

Qt的窗口系统

代码仓库以及参考文件见文章底部 坐标体系 要想学好GUI,界面的坐标系首先要搞清楚 在Qt编程中,以左上角为原点,X向右增加,Y向下增加。 对于所有嵌套的窗口,其坐标是相对于父窗口来说的。 QWidget 所有窗口以及窗口控件都是从QWidget直接或者间接派生出来的。 对象模…

VL系列 Exchanging-based Multimodal Fusion with Transformer 论文阅读笔记

多模态融合 Exchanging-based Multimodal Fusion with Transformer 论文阅读笔记 一、Abstract二、引言三、相关工作3.1 深度多模态融合 四、方法4.1 低维投影和 embedding 归一化低维投影Embedding 归一化 4.2 多模态交换Transformer 基础CrossTransformer 4.3 训练目标 五、实…

如何自己开发一个前端监控SDK

最近在负责团队前端监控系统搭建的任务。因为我们公司有统一的日志存储平台、日志清洗平台和基于 Grafana 搭建的可视化看板&#xff0c;就剩日志的采集和上报需要自己实现了&#xff0c;所以决定封装一个前端监控 SDK 来完成日志的采集和上报。 架构设计 因为想着以后有机会…

2023/09/08 qtc++ day3

自行封装一个栈的类&#xff0c;包含私有成员的属性&#xff1a;栈的数组&#xff0c;记录栈顶的变量 成员函数&#xff1a;构造函数、析构函数、拷贝构造函数、入栈、出栈、清空栈、判空、判满、获取栈顶元素、求站的大小 头文件 #ifndef STACK_H #define STACK_H #include …

el-table操作列动态自适应设置(根据操作项个数动态设置宽度)

一、目的 目的&#xff1a;表格操作列宽度&#xff0c;根据操作项多少&#xff0c;自动调节宽度背景&#xff1a;用el-table组件开发时&#xff0c;对于表格的操作列的自适应宽度是一个问题&#xff0c;如果不设置&#xff0c;操作按钮多时会有换行问题。如果设置最小宽度或宽…

Tomcat 的部署和优化

1、什么是Tomcat Tomcat&#xff1a;是一个免费的、开源的轻量级web应用服务器&#xff0c;普遍用于中小型系统和访问用户流量小的场合&#xff0c;由于是java语言所开发开发&#xff0c;所以要jdk环境 由 web容器、servlet容器、jsp容器构成 web容器&#xff1a;完成 Web 服…

个人主页网站动态星空背景源码(带后台版本)

动态星空背景个人主页网站源码是一种用于创建个人主页的开源项目。它具有一个令人印象深刻的动态星空背景&#xff0c;为用户提供了一个独特而吸引人的网页设计。此源码还包含一个后台版本&#xff0c;使用户能够轻松管理和更新他们的个人主页内容。 通过该源码&#xff0c;用…

stringBuffer.append(“字符串参数“);这个在字符串参数后添加空格怎么写

stringBuffer.append(“字符串参数”);这个在字符串参数后添加空格怎么写&#xff1f; 要在字符串参数后添加空格&#xff0c;可以直接在字符串参数的末尾使用空格字符&#xff0c;像这样&#xff1a; stringBuffer.append("字符串参数 ");这样就在字符串参数后添加…

试图替代 Python 的下一代AI编程语言:Mojo

文章目录 为什么叫 Mojo &#xff1f;Python 家族的一员&#xff0c;MojoPython 的好处&#xff1a;Python 兼容性Python 的问题移动和服务器部署&#xff1a;Python 子集和其他类似 Python 的语言&#xff1a; Mojo 是一种创新的编程语言&#xff0c;结合了 Python 的可用性和…

【Unity】 2D 游戏 库存模块实现

库存模块主要参考了 youtube 上的视频 BMo 的 Flexible INVENTORY SYSTEM in Unity with Events and Scriptable Objects 和 Simple Inventory UI in Unity With Grid Layouts 这两个视频是一个系列 还是一个视频也是 BMo的 How To INTERACT with Game Objects using UNITY E…

git:亲测体验rebase与merge

rebase与merge异同与最佳使用场景[1] 这个dev-cui分支从devlop分支切出后,一直都只有我一个人在开发&维护. 假如还有一位同事张三, 在devlop分支切出的分支dev-zhangsan上进行开发,他添加了一个glossary.md,而后进行了add & commit 此时项目开发完成,需要将两个分支合并…

【C++模拟实现】手撕AVL树

【C模拟实现】手撕AVL树 目录 【C模拟实现】手撕AVL树AVL树的介绍&#xff08;百度百科&#xff09;AVL树insert函数的实现代码验证是否为AVL树AVL树模拟实现的要点易忘点AVL树的旋转思路 作者&#xff1a;爱写代码的刚子 时间&#xff1a;2023.9.10 前言&#xff1a;本篇博客将…

《自然语言处理(NLP)的最新进展:Transformers与GPT-4的浅析》

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页——&#x1f405;&#x1f43e;猫头虎的博客&#x1f390; &#x1f433; 《面试题大全专栏》 &#x1f995; 文章图文…

Stable Diffusion 免费升级 SDXL 1.0,哪些新特性值得关注?体验如何?5 分钟带你体验!

一、引言 7 月 26 日&#xff0c;Stability AI 发布了 SDXL 1.0&#xff0c;号称目前为止&#xff0c;最厉害的开放式图像生成大模型。 它到底有没有网上说的那么炸裂&#xff1f;真的已经实现了像 midjourney 一样 靠嘴出图 的功能吗&#xff1f;相对于之前的版本&#xff0c;…

【redis进阶】Redis String数据类型为什么不好用

保存1 亿张10字节图片标识&#xff0c;String结构用了 6.4GB 的内存&#xff0c;为什么&#xff1f;如何优化&#xff1f; 数据量多时&#xff0c;比较占空间 存储数量量较多的时候&#xff0c;可以使用list数据结构来替代String&#xff0c;以二级编码的方式将数据存入redis…

[杂谈]-电动汽车有哪些不同类型

电动汽车有哪些不同类型&#xff1f; 文章目录 电动汽车有哪些不同类型&#xff1f;1、概述2、纯电动汽车&#xff08;BEV&#xff09;3、燃料电池电动汽车&#xff08;FCEV&#xff09;4、插电式混合动力汽车 (PHEV&#xff09;5、混合动力电动汽车 (HEV)6、轻度混合动力HEV7、…