std::mdspan 是 C++23 引入的核心新特性之一,用于提供对任意内存布局的多维数组的**非拥有式视图(view)**,类似 std::span 之于一维数组。它不管理内存,只记录起始地址、各维度大小和步长(stride),支持自定义布局(layout mapping)与访问器(accessor),灵活高效,特别适合科学计算、图像处理、线性代数库等场景。
最常见的是用默认布局 std::layout_right(行优先,类似 C 风格数组):
int data[12] = {0,1,2,3,4,5,6,7,8,9,10,11};
std::mdspan , std::extents> view(data); // 3×4 视图
// 等价写法(显式指定 layout)
std::mdspan, std::layout_right> view2(data);
std::cout << view(1, 2) << "\n"; // 输出 6(第1行第2列,0-indexed)
注意:std::extents 在编译期固定维度大小(如 表示 2D,大小分别为 3 和 4),也可用 dynamic_extent 表示运行时确定:
std::extents:第一维编译期为 3,第二维运行时传入std::mdspan> v(data, 4);
用 std::layout_left 实现列优先存储(即内存中按列连续):
int data_col[12]; std::mdspan, std::layout_left> col_view(data_col); // col_view(i,j) 对应内存位置:base + i + j*3
你也可以实现自己的 layout mapping 类型,只要满足标准要求(提供 mapping::operator()() 和 stride() 等接口),适用于分块、对角、稀疏等特殊布局。
默认 accessor 是 std::default_accessor,直接解引用指针。但你可以换用 std::submdspan 或自定义 accessor 来实现边界检查、缩放、只读、原子访问等:
std::mdspan 已隐含只读语义std::submdspan 切片子区域:auto sub = std::submdspan(view, std::tuple{1,3}, std::tuple{0,2}); → 取第1~2行、第0~1列目前(GCC 13+ / Clang 16+ / MSVC 19.35+)已初步支持,但部分细节仍在完善。使用前注意:
-std=c++23)且标准库支持 mdspan(如 libstdc++ ≥ 13.2,libc++ ≥ 16)std::extents)std::vector<:vector>>?不行——后者是非连续内存;mdspan 要求底层是连续/可映射的内存块std::mdspan 不是语法糖,而是为高性能数值计算设计的底层抽象。它把“形状”、“布局”、“访问”三者正交分离,让多维数组操作既安全又零成本。掌握它,就掌握了 C++23 在数据视图领域最关键的一步。