std::span 是 C++20 引入的轻量级非拥有式数组视图,仅持指针和长度,用于安全高效传递连续内存片段,避免拷贝与裸指针误用,支持编译期/运行期边界约束,但不管理内存生命周期。

std::span 是 C++20 引入的轻量级非拥有式数组视图,它不管理内存,只持有指向连续元素的指针和长度,用于安全、高效地传递数组或容器片段,避免不必要的拷贝和裸指针误用。
基本用法:构造与访问
span 可由原生数组、std::array、std::vector(或其他支持 data() + size() 的容器)构造,类型推导通常自动完成:
-
// 原生数组
int arr[] = {1, 2, 3, 4, 5};
std::spans1{arr}; // 推导为 span -
// std::array
std::arraya = {1.1, 2.2, 3.3};
std::spans2{a}; -
// std::vector(运行时大小)
std::vectorv(100);
std::spans3{v}; // span 等价于 span
关键安全特性:边界检查与静态约束
span 在编译期(固定大小)或运行期(动态大小)提供越界防护(仅在启用调试断言如 _ITERATOR_DEBUG_LEVEL=2 或使用 at() 时);更重要的是,它明确表达“我只读/写这一段”,并阻止隐式降维或越界切片:
- 使用
s.subspan(2, 3)安全获取子视图,超出范围会截断或返回空 span(不抛异常) -
s.first(3)和s.last(2)分别取前 N 个、后 N 个元素,同样做范围约束 - 若声明为
std::span,传入 5 元素数组会编译失败——强制匹配尺寸
函数参数设计:替代 T* + size_t 的现代写法
把 span 当作首选参数类型,能提升接口清晰度和安全性:
立即学习“C++免费学习笔记(深入)”;
-
// 旧方式:易错、无长度绑定
void process(int* data, size_t n); -
// 新方式:语义明确、自动适配多种来源
void process(std::spandata) {
for (int x : data) { /* ... */ }
} - 调用时可传
process(arr)、process(v)、process(v.subspan(1, 4)),无需手动传 size
注意事项与常见误区
span 本身不延长所指对象生命周期,使用时需确保源数据存活时间 ≥ span 生命周期:
- 不要返回局部数组的 span:
return std::span→ 悬垂视图{local_arr}; - 避免对临时容器取 span:
std::span→ vector 析构后 span 失效{std::vector {1,2,3}} - const span(如
span)保证不修改元素,但不阻止底层 const T 被修改(若原始指针非常量) - span 不是智能指针,不参与内存管理,也不提供迭代器以外的算法支持(需配合
std::ranges使用)










