std::span是C++20引入的轻量级数组视图,仅存储指针和长度、零开销,适用于函数参数传递连续内存(如vector/array/原始数组),避免裸指针+长度组合;不可用于存储数据或绑定局部数组以防悬垂。

std::span 是什么,什么时候该用它
它不是容器,是轻量级的数组视图——只存指针+长度,零开销。适合函数参数传递原始数组、std::array、std::vector 的连续数据段,避免传指针+长度的冗余组合,也比 std::vector 更轻(不管理内存)。别用它替代容器存数据,也别对栈上局部数组返回 std::span(悬垂风险)。
怎么构造 std::span,哪些构造方式安全
最常用的是从容器或数组推导:std::span arr{vec}、std::span arr{arr_data};C++20 支持 CTAD(类模板实参推导),不用写模板参数。但注意:
-
std::span<int> s{&x, 1}</int>合法,但&x必须指向生命周期足够长的内存 -
std::span<const int> s{vec}</const>可隐式转换,但std::span<int> s{vec_const}</int>编译失败(非常量视图不能绑定 const 数据) - 带长度检查的构造(如
std::span<int>{arr}</int>)会在编译期校验大小,越界直接报错,适合已知固定尺寸场景
常见错误:越界访问和生命周期陷阱
运行时不会做边界检查(除非开启调试断言,如 libstdc++ 的 _GLIBCXX_ASSERTIONS),s[100] 很可能静默越界。更隐蔽的问题是生命周期:
- 返回局部数组的
std::span:函数返回后视图悬垂,std::span{local_arr}是危险操作 - 传入临时
std::vector:如f(std::span{std::vector{1,2,3}}),临时对象在完整表达式结束即销毁,视图立刻失效 - 用
data()+size()手动构造时,确保两者来源一致(比如混用不同 vector 的data()和另一个的size())
和 raw pointer / gsl::span / std::string_view 对比要点
std::span 比裸指针多了长度信息和部分类型安全;相比 gsl::span,它是标准库正式成员,无需额外依赖;和 std::string_view 行为高度相似,但泛型支持任意元素类型。注意:
立即学习“C++免费学习笔记(深入)”;
- 没有
begin()/end()以外的迭代器适配(不支持rbegin()等反向迭代器) - 不提供
data()以外的数据修改接口(不能push_back或重分配) - 某些旧编译器(如 GCC 10 之前)对 CTAD 支持不全,显式写
std::span<int>{vec}</int>更稳妥
真正要小心的不是语法怎么写,而是谁拥有数据、谁负责生命周期——std::span 从不参与所有权管理,这点一旦忽略,调试成本远高于写错一个 for 循环。











