0

0

c++23的std::mdspan将如何改变数值计算? (多维数组视图)

裘德小鎮的故事

裘德小鎮的故事

发布时间:2026-01-10 00:49:34

|

164人浏览过

|

来源于php中文网

原创

std::mdspan是C++23引入的零开销多维数组视图,不拥有数据、不分配内存,仅持指针+维度大小+布局策略,不能替代std::vector;它要求底层为单块连续内存,适用于规则网格,不可用于std::vector等非连续结构。

c++23的std::mdspan将如何改变数值计算? (多维数组视图)

std::mdspan 是什么,它真能替代 std::vector<:vector>> 吗?

std::mdspan 是 C++23 引入的零开销多维数组视图(multi-dimensional array view),不拥有数据,只持有一个指针 + 各维度大小 + 布局策略。它不是容器,也不分配内存,类似 std::span 之于一维,但扩展到 N 维。

它不能直接替代 std::vector<:vector>>——后者是“锯齿数组”,每行可能不同长、内存不连续;而 std::mdspan 要求底层是单块连续内存(如 std::vector 或堆分配的 T*),适合规则网格(如图像、矩阵、张量)。

常见误用现象:试图用 std::mdspan 包装 std::vector<:vector>> 的首元素地址,结果访问越界或语义错乱。

正确姿势是:

立即学习C++免费学习笔记(深入)”;

  • std::vector 扁平化存储(行优先或列优先)
  • 构造 std::mdspan 时传入该向量的 .data() 和各维尺寸
  • 布局策略选 std::layout_right(默认,行优先)或 std::layout_left(列优先)

如何用 std::mdspan 表达二维矩阵并避免 stride 计算错误?

手动算下标(i * cols + j)容易出错,尤其切换语言或布局时。std::mdspan 把索引映射和步长(stride)封装进类型系统,编译期确定。

#include 
#include 

std::vector data(12); // 3×4 矩阵 auto mat = std::mdspan>( data.data(), std::extents{} );

mat(1, 2) = 3.14; // 自动转为 data[1*4 + 2] == data[6]

关键点:

Solvely
Solvely

AI学习伴侣,数学解体,作业助手,家教辅导

下载
  • std::extents 是编译期固定维度,不可运行时改变
  • 若需动态尺寸,用 std::extents,但会多存两个 size 值
  • 默认 std::layout_right:最后一维变化最快 → (i,j) 映射到 i * stride_1 + j,其中 stride_1 == 4
  • 误设 layout(比如用 layout_left 但按行优先填数据)会导致所有读写错位

与 Eigen / xtensor 相比,std::mdspan 的实际短板在哪?

std::mdspan 是视图,不是计算库。它不提供 .transpose().dot()、广播、表达式模板等。

典型缺失功能:

  • 没有内置矩阵乘法 —— 你仍得手写三重循环或调 BLAS
  • 不支持切片返回新 mdspan(如 mat.subspan(0,2, 1,3))—— C++26 才计划加入
  • 无自动内存管理 —— 不像 Eigen::MatrixXd 可直接构造并分配
  • 目前主流编译器(GCC 13/Clang 16)仅部分支持,MSVC 还在追赶;生产环境慎用于关键路径

但它带来的好处很实在:

  • 跨库互操作性提升:函数接口可统一用 std::mdspan 描述输入输出,避免为 Eigen/xtensor 写多套重载
  • 零拷贝传递:传一个 mdspan 比传 vector 或裸指针+尺寸三元组更安全、语义更清晰
  • 为未来标准数学库(如 std::linalg)铺路 —— C++26 的 std::linalg::matmul 就以 mdspan 为参数

你现在该不该在项目里立刻用 std::mdspan?

如果你的代码已用 std::vector 扁平化存多维数据,并频繁手算下标或封装自定义 Matrix 类,那么现在就可以小范围试水 std::mdspan —— 它几乎零成本,且让意图更明确。

但要注意这些现实约束:

  • 确保编译器版本 ≥ GCC 13.2 或 Clang 16,且开启 -std=c++2b
  • 避免依赖未标准化的扩展(如 submdspan),C++23 标准里它还不存在
  • 不要把它当“高级 vector”用 —— 它不管理内存,析构不释放资源,忘记维护底层数据生命周期会 crash
  • 调试时 IDE 可能不识别 mdspan 的 shape,打印需手动展开 extentsdata_handle

真正难的不是语法,是把“隐式维度约定”显式编码进类型 —— 比如一个 double* 到底是 3×4 还是 2×2×3,过去靠注释或命名,现在得靠 std::extents。这一步做错,后面所有计算都偏移。

相关专题

更多
c++怎么把double转成int
c++怎么把double转成int

本专题整合了 c++ double相关教程,阅读专题下面的文章了解更多详细内容。

51

2025.08.29

C++中int、float和double的区别
C++中int、float和double的区别

本专题整合了c++中int和double的区别,阅读专题下面的文章了解更多详细内容。

98

2025.10.23

硬盘接口类型介绍
硬盘接口类型介绍

硬盘接口类型有IDE、SATA、SCSI、Fibre Channel、USB、eSATA、mSATA、PCIe等等。详细介绍:1、IDE接口是一种并行接口,主要用于连接硬盘和光驱等设备,它主要有两种类型:ATA和ATAPI,IDE接口已经逐渐被SATA接口;2、SATA接口是一种串行接口,相较于IDE接口,它具有更高的传输速度、更低的功耗和更小的体积;3、SCSI接口等等。

1009

2023.10.19

PHP接口编写教程
PHP接口编写教程

本专题整合了PHP接口编写教程,阅读专题下面的文章了解更多详细内容。

57

2025.10.17

php8.4实现接口限流的教程
php8.4实现接口限流的教程

PHP8.4本身不内置限流功能,需借助Redis(令牌桶)或Swoole(漏桶)实现;文件锁因I/O瓶颈、无跨机共享、秒级精度等缺陷不适用高并发场景。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

353

2025.12.29

堆和栈的区别
堆和栈的区别

堆和栈的区别:1、内存分配方式不同;2、大小不同;3、数据访问方式不同;4、数据的生命周期。本专题为大家提供堆和栈的区别的相关的文章、下载、课程内容,供大家免费下载体验。

382

2023.07.18

堆和栈区别
堆和栈区别

堆(Heap)和栈(Stack)是计算机中两种常见的内存分配机制。它们在内存管理的方式、分配方式以及使用场景上有很大的区别。本文将详细介绍堆和栈的特点、区别以及各自的使用场景。php中文网给大家带来了相关的教程以及文章欢迎大家前来学习阅读。

567

2023.08.10

go语言 数组和切片
go语言 数组和切片

本专题整合了go语言数组和切片的区别与含义,阅读专题下面的文章了解更多详细内容。

46

2025.09.03

c++主流开发框架汇总
c++主流开发框架汇总

本专题整合了c++开发框架推荐,阅读专题下面的文章了解更多详细内容。

3

2026.01.09

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
最新Python教程 从入门到精通
最新Python教程 从入门到精通

共4课时 | 0.6万人学习

Rust 教程
Rust 教程

共28课时 | 4.2万人学习

Git 教程
Git 教程

共21课时 | 2.5万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号