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

C++20中的span容器

一.span容器

span 是 C++20 中引入的一个新的标准容器,它用于表示连续的一段内存区间,类似于一个轻量级的只读数组容器。

span 是一个轻量级非拥有式容器,它提供了对连续内存的引用。 span 的主要用途是作为函数参数,可以避免不必要的内存拷贝,并且可以防止悬垂指针和空指针引用的问题

它的定义在头文件 <span> 中,并位于 std 命名空间中。span 包含了一个指向连续内存区域的指针以及它所占用的大小,可以通过它来访问这个内存区域中的元素。

span 主要用于以下场景:

  1. 作为函数的参数,用于指示函数需要处理的数据范围;
  2. 作为类的成员变量,用于表示对象所管理的内存区域;
  3. 作为数组的视图,用于访问数组的一部分

二.span的用法

下面是几种 span 的用法示例:

1.将数组转换为 span:

int arr[] = {1, 2, 3, 4, 5};
span<int> s(arr, 5);

        这里将一个整型数组 arr 转换为 span 类型,并使用数组首地址和元素个数作为参数。

2.使用 span 来遍历一个容器:

vector<int> vec = {1, 2, 3, 4, 5};
for (auto&& x : span(vec)) {cout << x << " ";
}

这里使用 span(vec) 来构造一个 span 对象,遍历其中的元素并输出。

3.使用 span 来获取子序列:

int arr[] = {1, 2, 3, 4, 5};
span<int> s(arr, 5);
auto s1 = s.subspan(1, 3);

这里将一个 span 对象 s 分割为从第 1 个元素开始,长度为 3 的子序列,并将结果存储到 s1 中。

4.将 span 转换为其他容器类型:

int arr[] = {1, 2, 3, 4, 5};
span<int> s(arr, 5);
vector<int> vec(s.begin(), s.end());

这里使用 s.begin()s.end() 将 span 对象 s 转换为迭代器范围,并使用这个迭代器范围构造一个 vector 容器 vec

三.span的底层原理

下面为 span的简化版源码,用于展示其基本实现:

template<typename T, std::size_t Extent = std::dynamic_extent>
class span {
public:// 定义迭代器类型using iterator = T*;using const_iterator = const T*;// 构造函数constexpr span() noexcept : data_(nullptr), size_(0) {}constexpr span(T* ptr, std::size_t count) : data_(ptr), size_(count) {}template <std::size_t N>constexpr span(T(&arr)[N]) noexcept : data_(arr), size_(N) {}template <typename Container>constexpr span(Container& c) noexcept : data_(c.data()), size_(c.size()) {}// 拷贝构造函数和拷贝赋值运算符constexpr span(const span& other) noexcept = default;span& operator=(const span& other) noexcept = default;// 访问元素和迭代器操作constexpr T* data() const noexcept { return data_; }constexpr std::size_t size() const noexcept { return size_; }constexpr bool empty() const noexcept { return size_ == 0; }constexpr T& operator[](std::size_t idx) const { return data_[idx]; }constexpr T& front() const { return data_[0]; }constexpr T& back() const { return data_[size_-1]; }constexpr iterator begin() const noexcept { return data_; }constexpr iterator end() const noexcept { return data_ + size_; }constexpr const_iterator cbegin() const noexcept { return data_; }constexpr const_iterator cend() const noexcept { return data_ + size_; }private:T* data_;  // 元素指针std::size_t size_;  // 元素数量
};

具体实现方式是通过指针来引用连续的一段内存,从而实现 span 的基本功能。由于 span 没有实际的内存所有权,所以它不能拥有或释放内存。它只是提供了对现有内存块的访问。

标准库中的 span 还提供了一些其他的功能,比如对子区间的切片和子区间的迭代器等。实际的实现可能会更加复杂,但其基本的思想是一致的。

四.span 与 array ,vector ,数组指针 的区别

1. span 与 array ,vector的区别

span 是 C++20 中新增的一个轻量级容器,用于表示一段连续的内存区域,它不负责管理内存空间,也不会拥有所指向内存的所有权,只是提供一种方便的方式来操作内存区域,因此可以看做是一个只读的“裸指针”。

arrayvector 相比,span主要区别在于它不拥有自己的存储空间,而是引用了另一个数组或容器的内存空间。因此,当我们需要使用一个连续的内存块时,可以使用 span 来代替 arrayvector

具体来说,array 是一个固定大小的数组容器,其大小在编译时就确定了,不能动态改变。vector 是一个动态增长的数组容器,可以动态分配内存,并在需要时扩大容量。而 span 是一个非拥有型的容器,可以看作是一个指向连续内存区域的引用,可以指向任何类型的元素。

在使用方面,arrayvector 可以用来存储数据,并通过下标或迭代器来访问其中的元素;span 则更多地用来表示一段内存区域并提供类似于迭代器的操作来访问其中的元素(就是 只读),如 beginendrbeginrend 等。

总之,spanarrayvector 三者各有所长,可以根据实际需求来选择使用。

2. span 与 数组指针的区别

在C++中,数组和指针是密不可分的,它们常常被一起使用。然而,数组和指针不是相同的东西,它们有自己的属性和限制。同样地,span和指针也有很多区别,这里列举几点:

  1. span是一个封装了数组指针和长度的轻量级容器,它提供了对数组的安全访问。指针只是一个指向内存位置的地址,没有长度信息。因此,使用指针时需要显式地传递长度信息,否则可能会导致缓冲区溢出等问题。

  2. span支持范围操作,它可以使用STL中的算法和其他支持范围操作的库进行操作。指针只能通过指针运算和下标操作来访问和操作数据。

  3. span是可传递性的,可以传递到函数中作为参数,而指针不能。这是因为在函数中传递指针时,我们必须显式地传递指针所指向的内存块的大小,否则函数无法确定内存块的大小。

  4. span是一个类模板,可以指定数据类型和长度类型。指针只能指向特定类型的数据。

总的来说,span比指针更安全,更灵活,更易于使用,是一种更好的数组容器类型。

五.span的优点

std::span 的主要优点如下:

  1. 轻量级:std::span 本身只是一个轻量级的非拥有式容器,没有自己的内存管理,因此可以在不分配内存的情况下轻松地传递和操作数据。同时,std::span 的内存布局与原始数组相同,因此不需要进行数据的复制或重排。

  2. 安全性:std::span 具有边界检查机制,可以避免访问越界等错误,从而提高代码的安全性。

  3. 可组合性:std::span 可以与其他容器类型进行组合,例如可以从 std::vectorstd::array 中创建 std::span,或将 std::span 转换为 std::vectorstd::array

  4. 易于扩展:由于 std::span 只是一个非拥有式容器,因此可以轻松地将其用作接口的一部分,并以此扩展接口的功能。

总之,std::span 是一个非常实用的工具,可以方便地对数据进行访问和处理,同时也可以提高代码的可读性、可维护性和安全性。

具体一些相关的信息见:std::span - cppreference.com

相关文章:

C++20中的span容器

一.span容器 span 是 C20 中引入的一个新的标准容器&#xff0c;它用于表示连续的一段内存区间&#xff0c;类似于一个轻量级的只读数组容器。 span 是一个轻量级的非拥有式容器&#xff0c;它提供了对连续内存的引用。 span 的主要用途是作为函数参数&#xff0c;可以避免不…...

codeforces周赛div3#855记录

目录 总结 一&#xff0c;A. Is It a Cat? 二&#xff0c;B. Count the Number of Pairs 三&#xff0c;C1. Powering the Hero (easy version) 四&#xff0c;C2. Powering the Hero (hard version) 总结 真羡慕ACM校队的同学&#xff0c;能AC七八题&#xff0c;甚至ak …...

2022年考研结果已出,你上岸了吗?

官方公布&#xff1a;2022年考研人数为457万。 2月20号左右&#xff0c;全国考研分数已经陆续公布&#xff0c;现在已经过去一周左右的时间了&#xff0c;你上岸了吗&#xff0c;还是在等调剂&#xff0c;或者已经知道落榜不知道何去何从&#xff1f; 考研的热潮在近几年席卷…...

2023 工业互联网平台:智慧制硅厂 Web SCADA 生产线

我国目前是全球最大的工业硅生产国、消费国和贸易国&#xff0c;且未来该产业的主要增量也将来源于我国。绿色低碳发展已成为全球大趋势和国际社会的共识&#xff0c;随着我国“双碳”目标的推进&#xff0c;光伏产业链快速发展&#xff0c;在光伏装机需求的带动下&#xff0c;…...

6-2 SpringCloud快速开发入门:声明式服务消费 Feign实现消费者

声明式服务消费 Feign实现消费者 使用 Feign实现消费者&#xff0c;我们通过下面步骤进行&#xff1a; 第一步&#xff1a;创建普通 Spring Boot工程 第二步&#xff1a;添加依赖 <dependencies><!--SpringCloud 集成 eureka 客户端的起步依赖--><dependency>…...

Git-学习笔记01【Git简介及安装使用】

Java后端 学习路线 笔记汇总表【黑马-传智播客】Git-学习笔记01【Git简介及安装使用】Git-学习笔记02【Git连接远程仓库】Git-学习笔记03【Git分支】目录 01-git的历史 02-git和svn的对比 03-git的安装 04-向本地仓库中添加文件 05-修改文件内容并提交 06-删除本地仓库中…...

【Python】控制自己的手机拍照,并自动发送到邮箱

前言 嗨喽&#xff0c;大家好呀~这里是爱看美女的茜茜呐 今天这个案例&#xff0c;就是控制自己的摄像头拍照&#xff0c; 并且把拍下来的照片&#xff0c;通过邮件发到自己的邮箱里。 想完成今天的这个案例&#xff0c;只要记住一个重点&#xff1a;你需要一个摄像头 思路…...

八股文(二)

一、 实现深拷贝和浅拷贝 1.深拷贝 function checkType(any) {return Object.prototype.toString.call(any).slice(8, -1) }//判断拷贝的要进行深拷贝的是数组还是对象&#xff0c;是数组的话进行数组拷贝&#xff0c;对象的话进行对象拷贝 //如果获得的数据是可遍历的&#…...

在CANoe/CANalyzer中观察CAN Message报文的周期Cycle

案例背景&#xff1a; 该篇博文将告诉您&#xff0c;如何直观的&#xff0c;图示化的&#xff0c;查看CAN网络中各CAN Message报文的周期变化。 优质博文推荐阅读&#xff08;单击下方链接&#xff0c;即可跳转&#xff09;&#xff1a; Vector工具链 CAN Matrix DBC CAN M…...

Linux命令·ls

ls命令是linux下最常用的命令。ls命令就是list的缩写缺省下ls用来打印出当前目录的清单如果ls指定其他目录那么就会显示指定目录里的文件及文件夹清单。 通过ls 命令不仅可以查看linux文件夹包含的文件而且可以查看文件权限(包括目录、文件夹、文件权限)查看目录信息…...

Mysql InnoDB 存储引擎笔记

1 存储引擎 简介 Mysql 存储引擎有多种&#xff1a;包括 MyISAM、InnoDB 和 Memory。 其中MyISAM 和 INNODB 的区别&#xff1a; 事务安全&#xff08;MyISAM不支持事务&#xff0c;INNODB支持事务&#xff09;&#xff1b;外键 MyISAM 不支持外键&#xff0c; INNODB支持外…...

智慧工地AI视频分析系统 opencv

智慧工地AI视频分析系统通过pythonopencv网络模型图像识别技术&#xff0c;智慧工地AI视频分析算法自动识别现场人员穿戴是否合规。本算法模型中用到opencv技术&#xff0c;OpenCV基于C实现&#xff0c;同时提供python, Ruby, Matlab等语言的接口。OpenCV-Python是OpenCV的Pyth…...

小红书「高效达人筛选攻略」

三八女神节降临&#xff0c;诸多品牌纷纷开启铺垫预热&#xff0c;在各大平台借势宣传。而聚集庞大年轻女性消费群体的小红书&#xff0c;对“她营销”的重要性不言而喻。节点序幕拉开&#xff0c;面对海量达人信息&#xff0c;如何提前积草屯粮、高效备战&#xff1f; 本期千瓜…...

大话数据结构-线性表

1 定义 线性表是零个或多个数据元素的有限序列。 2 抽象数据类型 ADT 线性表(List)Data&#xff1a;线性表的数据对象集合为{al,a2,a3,....an}&#xff0c;每个元素的类型均为DataType。其中&#xff0c;除第一个元素a1外&#xff0c;每一个元素有且只有一个直接前驱元素&…...

分布式缓存 Memcached Linux 系统安装

1.Memcached简介 Memcached是一个开源、高性能&#xff0c;将数据分布于内存中并使用key-value存储结构的缓存系统。它通过在内存中缓存数据来减少向数据库的频繁访问连接的次数&#xff0c;可以提高动态、数据库驱动之类网站的运行速度。 Memcached在使用是比较简单的&#…...

【数据结构】链表:看我如何顺藤摸瓜

&#x1f451;专栏内容&#xff1a;数据结构⛪个人主页&#xff1a;子夜的星的主页&#x1f495;座右铭&#xff1a;日拱一卒&#xff0c;功不唐捐 文章目录一、前言二、链表1、定义2、单链表Ⅰ、新建一个节点Ⅱ、内存泄漏Ⅲ、插入一个节点Ⅳ、销毁所有节点Ⅴ、反转一个链表3、…...

linux shell 入门学习笔记18 函数开发

概念 函数就是将你需要执行的shell命令组合起来&#xff0c;组成一个函数体。一个完整的函数包括函数头和函数体&#xff0c;其中函数名就是函数的名字。 优点 将相同的程序&#xff0c;定义&#xff0c;封装为一个函数&#xff0c;能减少程序的代码数量&#xff0c;提高开发…...

如何最巧妙回答HR面试“送命题”:你为什么离开上家公司?

一 HR面试存在“送命题”? 一个资深HR朋友聊到,他最近pass掉一个名校高材生。 其实洽谈过程还比较愉悦,小姑娘名校毕业,落落大方,薪酬要求比较合理,各方面都比较符合,最后就在决定要录用时,HR朋友随口问了句 “你为什么离开上家公司?”,小姑娘也是随口说了句“我不喜…...

注意力机制详解系列(五):分支与时间注意力机制

&#x1f468;‍&#x1f4bb;作者简介&#xff1a; 大数据专业硕士在读&#xff0c;CSDN人工智能领域博客专家&#xff0c;阿里云专家博主&#xff0c;专注大数据与人工智能知识分享&#xff0c;公众号&#xff1a;GoAI的学习小屋&#xff0c;免费分享书籍、简历、导图等资料&…...

创宇盾重保经验分享,看政府、央企如何防护?

三月重保已经迫近&#xff0c;留给我们的准备时间越来越少&#xff0c;综合近两年三月重保经验及数据总结&#xff0c;知道创宇用实际案例的防护效果说话&#xff0c;深入解析为何创宇盾可以在历次重保中保持“零事故”成绩&#xff0c;受到众多部委、政府、央企/国企客户的青睐…...

业务系统对接大模型的基础方案:架构设计与关键步骤

业务系统对接大模型&#xff1a;架构设计与关键步骤 在当今数字化转型的浪潮中&#xff0c;大语言模型&#xff08;LLM&#xff09;已成为企业提升业务效率和创新能力的关键技术之一。将大模型集成到业务系统中&#xff0c;不仅可以优化用户体验&#xff0c;还能为业务决策提供…...

日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする

日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする 1、前言(1)情况说明(2)工程师的信仰2、知识点(1) にする1,接续:名词+にする2,接续:疑问词+にする3,(A)は(B)にする。(2)復習:(1)复习句子(2)ために & ように(3)そう(4)にする3、…...

Redis相关知识总结(缓存雪崩,缓存穿透,缓存击穿,Redis实现分布式锁,如何保持数据库和缓存一致)

文章目录 1.什么是Redis&#xff1f;2.为什么要使用redis作为mysql的缓存&#xff1f;3.什么是缓存雪崩、缓存穿透、缓存击穿&#xff1f;3.1缓存雪崩3.1.1 大量缓存同时过期3.1.2 Redis宕机 3.2 缓存击穿3.3 缓存穿透3.4 总结 4. 数据库和缓存如何保持一致性5. Redis实现分布式…...

Mybatis逆向工程,动态创建实体类、条件扩展类、Mapper接口、Mapper.xml映射文件

今天呢&#xff0c;博主的学习进度也是步入了Java Mybatis 框架&#xff0c;目前正在逐步杨帆旗航。 那么接下来就给大家出一期有关 Mybatis 逆向工程的教学&#xff0c;希望能对大家有所帮助&#xff0c;也特别欢迎大家指点不足之处&#xff0c;小生很乐意接受正确的建议&…...

OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别

OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别 直接训练提示词嵌入向量的核心区别 您提到的代码: prompt_embedding = initial_embedding.clone().requires_grad_(True) optimizer = torch.optim.Adam([prompt_embedding...

爬虫基础学习day2

# 爬虫设计领域 工商&#xff1a;企查查、天眼查短视频&#xff1a;抖音、快手、西瓜 ---> 飞瓜电商&#xff1a;京东、淘宝、聚美优品、亚马逊 ---> 分析店铺经营决策标题、排名航空&#xff1a;抓取所有航空公司价格 ---> 去哪儿自媒体&#xff1a;采集自媒体数据进…...

基于Java Swing的电子通讯录设计与实现:附系统托盘功能代码详解

JAVASQL电子通讯录带系统托盘 一、系统概述 本电子通讯录系统采用Java Swing开发桌面应用&#xff0c;结合SQLite数据库实现联系人管理功能&#xff0c;并集成系统托盘功能提升用户体验。系统支持联系人的增删改查、分组管理、搜索过滤等功能&#xff0c;同时可以最小化到系统…...

算法岗面试经验分享-大模型篇

文章目录 A 基础语言模型A.1 TransformerA.2 Bert B 大语言模型结构B.1 GPTB.2 LLamaB.3 ChatGLMB.4 Qwen C 大语言模型微调C.1 Fine-tuningC.2 Adapter-tuningC.3 Prefix-tuningC.4 P-tuningC.5 LoRA A 基础语言模型 A.1 Transformer &#xff08;1&#xff09;资源 论文&a…...

AI病理诊断七剑下天山,医疗未来触手可及

一、病理诊断困局&#xff1a;刀尖上的医学艺术 1.1 金标准背后的隐痛 病理诊断被誉为"诊断的诊断"&#xff0c;医生需通过显微镜观察组织切片&#xff0c;在细胞迷宫中捕捉癌变信号。某省病理质控报告显示&#xff0c;基层医院误诊率达12%-15%&#xff0c;专家会诊…...

JS手写代码篇----使用Promise封装AJAX请求

15、使用Promise封装AJAX请求 promise就有reject和resolve了&#xff0c;就不必写成功和失败的回调函数了 const BASEURL ./手写ajax/test.jsonfunction promiseAjax() {return new Promise((resolve, reject) > {const xhr new XMLHttpRequest();xhr.open("get&quo…...