我的编程空间,编程开发者的网络收藏夹
学习永远不晚

C++20中的span容器及用法小结

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

C++20中的span容器及用法小结

一.span容器

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

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

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

span 主要用于以下场景:

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

二.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和指针也有很多区别,这里列举几点:

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

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

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

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

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

五.span的优点

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

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

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

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

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

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

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

到此这篇关于C++20中的span容器的文章就介绍到这了,更多相关C++20中的span内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

C++20中的span容器及用法小结

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

C++20中的span容器及用法小结

std::span是一个非常实用的工具,可以方便地对数据进行访问和处理,同时也可以提高代码的可读性、可维护性和安全性,这篇文章主要介绍了C++20中的span容器,需要的朋友可以参考下
2023-03-06

C++20中的span容器怎么使用

这篇“C++20中的span容器怎么使用”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“C++20中的span容器怎么使用”文
2023-07-05

C# 中SqlParameter类的使用方法小结

在C#中,SqlParameter类用于表示SQL命令中的参数。以下是SqlParameter类的使用方法的小结:1. 创建SqlParameter对象:```SqlParameter parameter = new SqlParamete
2023-09-08

vue3中hooks的概述及用法小结

这篇文章是介绍一下vue3中的hooks以及它的用法,主要围绕两点来介绍,一个是hooks基本概念,另一个是vue3中hooks的使用方法,本文结合实例代码给大家讲解的非常详细,需要的朋友参考下吧
2023-03-07

Spring MVC中的常用注解及用法小结

本文详解了SpringMVC中常用的注解及用法。控制器注解:@Controller、@RequestMapping、@RequestParam、@PathVariable、@ResponseBody。数据绑定注解:@ModelAttribute、@Valid、@InitBinder。视图注解:@View、@Redirect、@FlashAttributes。其他注解:@Scope、@Component、@Autowired、@Qualifier、@ExceptionHandler。配有注解用法实例,清晰明
Spring MVC中的常用注解及用法小结
2024-04-02

C语言中getchar()函数的用法小结

这篇文章主要介绍了C语言中getchar()函数的用法,getchar是输入函数,输入的过程是什么呢,本文给大家详细讲解,对C语言getchar()函数相关知识感兴趣的朋友一起看看吧
2022-11-13

C++中的各种容器的使用方法汇总

这篇文章主要介绍了C++中的各种容器的使用方法,本文结合示例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
2023-01-10

C++中常见的容器使用问题及修复方案

C++中常见的容器使用问题及修复方案引言:在C++中,容器是一种非常重要的数据结构,用于存储和管理数据。STL(Standard Template Library)提供了许多容器类型,如vector、list、map等,它们可以极大地简化程
2023-10-22

C++ 元编程在自定义容器和数据结构中的应用?

元编程可用于创建自定义容器和数据结构。自定义容器:可定制行为和特性,如线程安全和动态大小,例:定制化的链表。数据结构:可定制结构,如高度和节点类型,例:高度为 2 或 3 的二叉树。C++ 元编程在自定义容器和数据结构中的应用元编程是一种
C++ 元编程在自定义容器和数据结构中的应用?
2024-05-21

C++中四种对象生存期和作用域以及static的用法总结分析

以下是对C++中四种对象生存期和作用域以及static的用法进行了详细的介绍,需要的朋友可以过来参考下
2022-11-15

C++ 函数内存分配和销毁在容器和算法中的应用

在 c++++ 中,内存通过动态分配器(new 和 delete)进行分配和销毁,用于管理容器和算法中的内存。容器(如 vector、list 和 map)自动处理内存,使用 raii 原则进行分配和释放。算法可以使用动态分配(如归并排序)
C++ 函数内存分配和销毁在容器和算法中的应用
2024-04-22

C#中泛型容器Stack<T>的用法并实现”撤销/重做”功能

这篇文章介绍了C#中泛型容器Stack<T>的用法并实现”撤销/重做”功能,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
2022-11-13

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录