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

C++23 std::mdspan:多维数组处理新利器

文章目录

    • 引言
    • C++23简介
    • std::mdspan的定义与特点
      • 定义
      • 特点
    • std::mdspan的优势
      • 零成本抽象的多维数据访问
      • 减少内存开销
      • 提高代码灵活性
    • std::mdspan的应用场景
      • 科学计算
      • 图形学
    • 相关提案
    • 示例代码
      • 使用动态扩展
      • 使用静态和动态扩展
    • 总结

引言

在C++的发展历程中,每一个新版本都带来了一些令人瞩目的新特性,以提升语言的功能和开发效率。C++23也不例外,其中std::mdspan作为一个重要的新特性,为开发者提供了一种灵活且高效的方式来处理多维数组和矩阵。本文将详细介绍std::mdspan的相关内容,包括其定义、特点、优势、应用场景以及相关提案。

C++23简介

C++23是C++语言的最新版本,它在C++20的基础上进行了补充和优化,引入了许多新特性和改进,旨在进一步提升C++语言的功能和开发效率。与C++20相比,C++23的变化虽然没有那么显著,但依然对语言的稳固性和可用性做出了许多重要改进。C++23的新特性包括明确的对象参数(Deducing this)、if consteval、多维下标运算符、内建衰减复制支持、标记不可达代码(std::unreachable)、平台无关的假设([[assume]])、命名通用字符转义、扩展基于范围的for循环中临时变量的生命周期、constexpr增强、简化的隐式移动、静态运算符static operator[]以及类模板参数推导(Class Template Argument Deduction from Inherited Constructors)等。此外,C++23还对标准库进行了重要更新,增加了新的容器类型如flat_mapflat_set,引入了多维视图(mdspan)以及标准生成器协程(Generator Coroutines),并改进了字符串格式化和错误处理机制(如std::expected)。

std::mdspan的定义与特点

定义

在C++23中,std::mdspan是一个非拥有的多维视图,用于表示连续对象序列。这个连续对象序列可以是一个简单的C数组、带有大小的指针、std::arraystd::vectorstd::string。这种多维视图通常被称为多维数组。其定义如下:

template<class T,class Extents,class LayoutPolicy = std::layout_right,class AccessorPolicy = std::default_accessor<T>
> class mdspan;
  • T:连续对象序列的类型。
  • Extents:指定维数及其大小;每个维度可以有静态或动态的扩展。
  • LayoutPolicy:指定用于访问底层内存的布局策略。
  • AccessorPolicy:指定如何引用底层元素。

由于C++17中的类模板参数推导(CTAD),编译器通常可以自动从初始化器的类型推导出模板参数。

特点

  1. 非拥有性std::mdspan并不拥有它所引用的数据,它只是一个视图,这意味着它不会负责数据的生命周期管理。这使得它在处理大型数据时非常高效,因为不需要进行数据的复制。
  2. 多维支持:可以方便地处理多维数组,通过指定不同的维度大小和布局策略,可以灵活地表示各种多维数据结构。
  3. 静态和动态扩展:每个std::mdspan的维度可以有静态或动态的扩展。静态扩展意味着其长度在编译时指定;动态扩展意味着其长度在运行时指定。

std::mdspan的优势

零成本抽象的多维数据访问

std::mdspan提供了零成本抽象的多维数据访问,为科学计算和图形学提供了标准方案。它允许开发者像操作多维数组一样方便地操作自定义容器,提高了代码的可读性和可维护性。例如:

#include <mdspan>
#include <vector>int main() {std::vector<double> buffer(1024);std::mdspan mat(buffer.data(), 32, 32); // 32x32矩阵视图mat[3, 4] = 2.718; // 多维下标运算符return 0;
}

减少内存开销

由于std::mdspan是非拥有的,它不会复制数据,因此可以减少内存开销。特别是在处理大型数据集时,这一优势更加明显。

提高代码灵活性

std::mdspan允许指定不同的布局策略和访问器策略,这使得它可以适应各种不同的数据存储方式和访问需求。例如,可以使用std::layout_left(Fortran或MATLAB风格)来替代默认的std::layout_right(C、C++或Python风格)。

std::mdspan的应用场景

科学计算

在科学计算中,经常需要处理多维数组和矩阵。std::mdspan可以方便地对这些数据进行操作,提高计算效率和代码的可读性。例如,在数值模拟、机器学习等领域,多维数组的处理是非常常见的,std::mdspan可以很好地满足这些需求。

图形学

在图形学中,图像、纹理等数据通常以多维数组的形式存储。std::mdspan可以用于高效地访问和处理这些数据,例如进行图像滤波、纹理映射等操作。

相关提案

std::mdspan相关的提案包括P0009R18、P2599R2、P2604R0、P2613R1、P2763R1等。这些提案对std::mdspan的功能和实现进行了不断的完善和优化。例如,P0009R18是关于std::mdspan的主要提案,它为std::mdspan的引入奠定了基础;P2599R2对std::mdspan的一些类型进行了修改;P2604R0增加了一些成员函数和类型;P2613R1添加了empty()成员函数;P2763R1对layout_stride的默认构造函数进行了修复。

示例代码

使用动态扩展

#include <mdspan>
#include <iostream>
#include <vector>int main() {std::vector myVec{1, 2, 3, 4, 5, 6, 7, 8};std::mdspan m{myVec.data(), 2, 4};std::cout << "m.rank(): " << m.rank() << '\n';for (std::size_t i = 0; i < m.extent(0); ++i) {for (std::size_t j = 0; j < m.extent(1); ++j) {std::cout << m[i, j] << ' ';}std::cout << '\n';}std::cout << '\n';std::mdspan m2{myVec.data(), 4, 2};std::cout << "m2.rank(): " << m2.rank() << '\n';for (std::size_t i = 0; i < m2.extent(0); ++i) {for (std::size_t j = 0; j < m2.extent(1); ++j) {std::cout << m2[i, j] << ' ';}std::cout << '\n';}return 0;
}

使用静态和动态扩展

#include <mdspan>
#include <iostream>
#include <vector>int main() {std::vector myVec{1, 2, 3, 4, 5, 6, 7, 8};std::mdspan<int, std::extents<std::size_t, 2, 4>> m{myVec.data()};std::cout << "m.rank(): " << m.rank() << '\n';for (std::size_t i = 0; i < m.extent(0); ++i) {for (std::size_t j = 0; j < m.extent(1); ++j) {std::cout << m[i, j] << ' ';}std::cout << '\n';}std::cout << '\n';std::mdspan<int, std::extents<std::size_t, std::dynamic_extent, std::dynamic_extent>> m2{myVec.data(), 4, 2};std::cout << "m2.rank(): " << m2.rank() << '\n';for (std::size_t i = 0; i < m2.extent(0); ++i) {for (std::size_t j = 0; j < m2.extent(1); ++j) {std::cout << m2[i, j] << ' ';}std::cout << '\n';}std::cout << '\n';return 0;
}

总结

std::mdspan是C++23中一个非常实用的新特性,它为开发者提供了一种灵活、高效的方式来处理多维数组和矩阵。通过其非拥有性、多维支持、静态和动态扩展等特点,std::mdspan在科学计算、图形学等领域有着广泛的应用前景。同时,相关的提案也在不断地完善和优化std::mdspan的功能,使其更加强大和易用。

相关文章:

C++23 std::mdspan:多维数组处理新利器

文章目录 引言C23简介std::mdspan的定义与特点定义特点 std::mdspan的优势零成本抽象的多维数据访问减少内存开销提高代码灵活性 std::mdspan的应用场景科学计算图形学 相关提案示例代码使用动态扩展使用静态和动态扩展 总结 引言 在C的发展历程中&#xff0c;每一个新版本都带…...

基于高德MCP2.0的智能旅游攻略系统设计与实现

前言&#xff1a;旅游规划的技术革命 在数字化旅游时代&#xff0c;MCP2.0&#xff08;Map-based Collaborative Planning&#xff09;系统代表着旅游攻略技术的最新演进。作为对1.0版本的全面升级&#xff0c;MCP2.0通过深度整合高德地图API和智能算法&#xff0c;实现了从静…...

【时时三省】(C语言基础)用函数实现模块化程序设计

山不在高&#xff0c;有仙则名。水不在深&#xff0c;有龙则灵。 ----CSDN 时时三省 为什么要用函数&#xff1f; 已经能够编写一些简单的C程序&#xff0c;但是如果程序的功能比较多&#xff0c;规模比较大&#xff0c;把所有的程序代码都写在一个主函数(main函数)中&#x…...

Flink流处理:实时计算URL访问量TopN(基于时间窗口)

目录 代码分析 背景知识拓展 代码调优 1. 性能优化 1.1 使用 KeyedStream 和 ProcessWindowFunction 替代 windowAll 1.2 使用 ReduceFunction 优化聚合 2. 功能扩展 2.1 支持动态窗口大小 2.2 支持多维度统计 2.3 支持持久化存储 3. 代码可读性 3.1 提取公共逻辑 …...

初识函数------了解函数的定义、函数的参数、函数的返回值、说明文档的书写、函数的嵌套使用、变量的作用域(全局变量与局部变量)

文章目录 一、什么是函数&#xff1f;二、函数定义与调用2.1 基本语法2.2 示例演示 三、函数参数详解3.1 位置参数3.2 默认参数3.3 可变参数3.4 关键字参数 四、返回值与文档说明4.1 返回多个值4.2 编写文档字符串 五、函数嵌套与作用域5.1 嵌套函数示例5.2 变量作用域5.3 glob…...

java collection集合特点知识点详解

在 Java 中&#xff0c;Collection 是所有集合类的根接口&#xff0c;它定义了一组对象的基本操作。Java 集合框架提供了丰富的实现类&#xff08;如List、Set、Queue&#xff09;&#xff0c;具有以下核心特点&#xff1a; 一、统一的接口设计 1. 核心接口层次 Collection …...

ngx_http_realip_module 模块概述

一、使用场景 日志记录 记录真实客户端 IP 而非反向代理的 IP&#xff0c;有助于流量分析和安全审计。访问控制 基于真实 IP 实现防火墙规则&#xff08;allow/deny&#xff09;或限流&#xff0c;而非误将上游 IP 视为客户端。GeoIP、WAF、限速等功能 模块化的上游真实 IP 支…...

自定义CString类与MFC CString类接口对比

接口对比表格 功能分类 你的 CString 接口 MFC CString 接口&#xff08;ANSI&#xff09; 一致性 差异说明 构造函数 CString() CString(const char*) CString(char) CString(const CString&) CString() CString(LPCSTR) CString(TCHAR) CString(const CString&…...

华为OD机试真题——考勤信息(2025A卷:100分)Java/python/JavaScript/C/C++/GO最佳实现

2025 A卷 100分 题型 本专栏内全部题目均提供Java、python、JavaScript、C、C++、GO六种语言的最佳实现方式; 并且每种语言均涵盖详细的问题分析、解题思路、代码实现、代码详解、3个测试用例以及综合分析; 本文收录于专栏:《2025华为OD真题目录+全流程解析+备考攻略+经验分…...

Go语言测试用例的执行与分析

在软件开发过程中&#xff0c;测试用例是确保代码质量的关键环节。Go语言作为一种现代的编程语言&#xff0c;它内置了强大的测试框架&#xff0c;可以帮助开发者轻松编写和执行测试用例。本文将介绍如何在 Go 语言中编写、执行测试用例&#xff0c;并对测试结果进行分析。 ## …...

vue3 vite 路由

如路由是这种格式 http://localhost:7058/admin/product/brand路由配置如下 import { createRouter, createWebHistory } from vue-router import HomeView from ../views/HomeView.vue import NProgress from nprogress; import nprogress/nprogress.css; import {errorRour…...

MyBatis:动态SQL

文章目录 动态SQLif标签trim标签where标签set标签foreach标签include标签和sql标签 Mybatis动态SQL的官方文档&#xff1a; https://mybatis.net.cn/dynamic-sql.html 动态SQL 动态SQL是 MyBatis的强大特性之一,如果是使用JDBC根据不同条件拼接sql很麻烦&#xff0c;例如拼接…...

游戏引擎学习第280天:精简化的流式实体sim

回顾并为今天的内容做铺垫 今天的任务是让之前关于实体存储方式的改动真正运行起来。我们现在希望让实体系统变得更加真实和实用&#xff0c;能够支撑我们游戏实际所需的功能。这就要求我们对它进行更合理的实现和调试。 昨天我们基本让代码编译通过了&#xff0c;但实际上还…...

femap许可与多用户共享

随着电磁仿真技术的发展&#xff0c;Femap作为一款领先的工具&#xff0c;在多个领域中发挥着不可替代的作用。然而&#xff0c;对于许多团队和企业来说&#xff0c;如何高效、经济地管理和使用Femap许可证成为了一个亟待解决的问题。本文将探讨Femap许可与多用户共享的概念、优…...

王树森推荐系统公开课 排序03:预估分数融合

融合预估分数 p c l i c k ⋅ p l i k e p_{click} \cdot p_{like} pclick​⋅plike​ 有实际意义&#xff0c;等于在曝光中点赞的概率。 p c l i c k ⋅ p c o l l e c t p_{click} \cdot p_{collect} pclick​⋅pcollect​ 同理。 按多种排名做 ensemble sort。 某电商的融…...

网络I/O学习-poll(三)

一、为什么要用Poll 由于select参数太多&#xff0c;较于复杂&#xff0c;调用起来较为麻烦&#xff1b;poll对其进行了优化 二、poll机制 poll也是一个系统调用&#xff0c;每次调用都会将所有客户端的fd拷贝到内核空间&#xff0c;然后进行轮询&#xff0c;判断IO是否就绪…...

k8s(12) — 版本控制和滚动更新(金丝雀部署理念)

金丝雀部署简介&#xff1a; 1、基本概念 金丝雀部署是一种软件开发中的渐进式发布策略&#xff0c;其核心思想是通过将新版本应用逐步发布给一小部分用户&#xff08;即 “金丝雀” 用户&#xff09;&#xff0c;在真实环境中验证功能稳定性和性能表现&#xff0c;再逐步扩大发…...

【git config --global alias | Git分支操作效率提升实践指南】

git config --global alias | Git分支操作效率提升实践指南 背景与痛点分析 在现代软件开发团队中&#xff0c;Git分支管理是日常工作的重要组成部分。特别是在规范的开发流程中&#xff0c;我们经常会遇到类似 feature/user-management、bugfix/login-issue 或 per/cny/dev …...

chrome源码中WeakPtr 跨线程使用详解:原理、风险与最佳实践

base::WeakPtr 在 Chromium 中 不能安全地跨线程使用。这是一个很关键的点&#xff0c;下面详细解释原因及正确用法。 &#x1f50d;原理与使用 ✅ 先说答案&#xff1a; base::WeakPtr 本质上是**线程绑定&#xff08;thread-affine&#xff09;**的。不能在多个线程之间创建…...

【Go】从0开始学习Go

文章目录 从0开始学习Go0 与C对比1 代码框架1.1 helloworld式代码示例1.2 主体代码元素&#xff08;核心三部分&#xff09;1.3 其他 2 与C/C区别3 有用的小工具4 注意事项 从0开始学习Go 0 与C对比 特性CGo编译型语言需要编译为机器码直接编译为二进制可执行文件静态类型类型…...

Windows 安装显卡驱动

1.第一步&#xff1a;打开Nvidia 官网驱动下载页面 2.第二步&#xff1a;选择相关信息&#xff0c; 玩游戏选择&#xff0c;GeForce Game Ready ,创意设计、摄影直播 选择 NVIDIA Studio 驱动程序 &#xff08;NVIDIA Studio Driver - WHQL.&#xff09; 2.第三步&#xff1…...

模块与包的导入

一、导入官方库 我们复盘下学习python的逻辑&#xff0c;所谓学习python就是学习python常见的基础语法学习你所处理任务需要用到的第三方库 类别典型库解决的问题学习门槛基础工具os、sys、json操作系统交互、序列化数据&#xff08;如读写 JSON 文件&#xff09;低科学计算n…...

Google设置app-ads.txt

问题&#xff1a; 应用上架后admob后台显示应用广告投放量受限&#xff0c;需要设置app-ads.txt才行。 如何解决&#xff1a; 官方教程: 看了下感觉不难&#xff0c;创建一个txt&#xff0c;将第二条的代码复制进行就得到app-ads.txt了。 然后就是要把这个txt放到哪才可以…...

docker安装rockerMQ

参考Docker部署RocketMQ5.x (单机部署配置参数详解不使用docker-compose直接部署)_rocketmq不推荐用docker部署-CSDN博客 镜像拉取 镜像地址&#xff1a; https://hub.docker.com/r/apache/rocketmq/tags 我在部署的时候最新发行版是5.1.0可以根据需求自行选择一个5.x的版本&a…...

交叉引用、多个参考文献插入、跨文献插入word/wps中之【插入[1-3]、连续文献】

我们在写论文时&#xff0c;需要插入大量参考文献。 有时&#xff0c;一句话需要引用多个文献&#xff0c;如&#xff1a;[1-3]或者[1,3,4]这种形式多个文献插入、跨文献插入。 在上一篇文章中&#xff0c;我们提到可以直接打“-”或者“&#xff0c;”&#xff0c;但是word导出…...

PLC双人舞:profinet转ethernet ip网关奏响施耐德与AB的协奏曲

PLC双人舞&#xff1a;ethernet ip转profinet网关奏响施耐德与AB的协奏曲 案例分析&#xff1a;施耐德PLC与AB PLC的互联互通 在现代工业自动化中&#xff0c;设备之间的互联互通至关重要。本案例旨在展示如何通过北京倍讯科技的EtherNet/IP转Modbus网关&#xff0c;将施耐德P…...

Image and depth from a conventional camera with a coded aperture论文阅读

Image and depth from a conventional camera with a coded aperture 1. 研究目标与实际意义1.1 研究目标1.2 实际问题与产业意义2. 创新方法:编码光圈设计与统计模型2.1 核心思路2.2 关键公式与模型架构2.2.1 图像形成模型2.2.2 深度可区分性准则2.2.3 统计模型与优化框架2.2…...

缺乏团队建设活动,如何增强凝聚力?

当一个团队缺乏系统性的建设活动时&#xff0c;成员之间容易产生疏离感、误解与信任缺失&#xff0c;最终影响整体执行力和目标达成。要有效增强团队凝聚力&#xff0c;应从设计高参与感的团队活动、结合业务与人文目标、营造持续共创的文化机制、推动跨层级协作互动等层面着手…...

特征筛选方法总结

非模型方法 一.FILTER过滤法&#xff1a; 1.缺失值比例&#xff08;80%以上缺失则删除&#xff09;/方差 注意&#xff1a; 连续变量只删方差为0的&#xff0c;因为变量取值范围会影响方差大小。 离散类的看各类取值占比,如果是三分类变量可以视作连续变量。 函数&#xff1a;V…...

力扣HOT100之二叉树:230. 二叉搜索树中第 K 小的元素

这道题直接用最笨的办法来做的&#xff0c;用递归来做&#xff0c;我们定义一个全局变量vector<int> element&#xff0c;然后使用中序遍历&#xff0c;每当碰到一个非空节点就将其加入到向量中&#xff0c;这样依赖当向量中的元素小于k时&#xff0c;就返回0&#xff0c…...