std::mdspan是C++23引入的零开销多维数组视图,不拥有数据、不分配内存,仅持指针+维度大小+布局策略,不能替代std::vector;它要求底层为单块连续内存,适用于规则网格,不可用于std::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(列优先)手动算下标(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]
关键点:
std::extents 是编译期固定维度,不可运行时改变std::extents,但会多存两个 size 值std::layout_right:最后一维变化最快 → (i,j) 映射到 i * stride_1 + j,其中 stride_1 == 4
layout_left 但按行优先填数据)会导致所有读写错位std::mdspan 是视图,不是计算库。它不提供 .transpose()、.dot()、广播、表达式模板等。
典型缺失功能:
mdspan(如 mat.subspan(0,2, 1,3))—— C++26 才计划加入Eigen::MatrixXd 可直接构造并分配但它带来的好处很实在:
std::mdspan 描述输入输出,避免为 Eigen/xtensor 写多套重载mdspan 比传 vector 或裸指针+尺寸三元组更安全、语义更清晰std::linalg)铺路 —— C++26 的 std::linalg::matmul 就以 mdspan 为参数如果你的代码已用 std::vector 扁平化存多维数据,并频繁手算下标或封装自定义 Matrix 类,那么现在就可以小范围试水 std::mdspan —— 它几乎零成本,且让意图更明确。
但要注意这些现实约束:
-std=c++2b
submdspan),C++23 标准里它还不存在mdspan 的 shape,打印需手动
展开 extents 和 data_handle
真正难的不是语法,是把“隐式维度约定”显式编码进类型 —— 比如一个 double* 到底是 3×4 还是 2×2×3,过去靠注释或命名,现在得靠 std::extents。这一步做错,后面所有计算都偏移。