std::span 是 C++20 引入的一个轻量级、非拥有型的数组视图(array view),它不管理内存,只保存指向连续元素的指针和元素个数,用于安全、高效地传递和操作原始数组、std::array、std::vector 等连续内存块。
传统上,C++ 函数若要接受“一段连续数据”,常依赖裸指针 + 长度(如 int* data, size_t n)或迭代器对,但容易出错:指针可能为空、长度可能与实际不匹配、类型信息丢失、无法自动推导大小。std::span 把指针和长度封装成一个类型安全、可拷贝、有边界检查(可选)、支持范围 for 的对象,同时零开销——它本身只有两个成员(指针 + size_t),无动态分配,无虚函数。
std::span 的模板参数是元素类型和扩展长度(std::dynamic_extent 表示运行时确定,最常用):
std::span —— 最常见,长度在运行时确定std::span —— 编译期固定长度,能从 std::array
隐式构造它支持多种构造来源:
int a[] = {1,2,3}; std::span s{a};(自动推导长度为 3)std::array arr = {4,5,6}; std::span s{arr};
std::vector v = {7,8,9}; std::span s{v};
std::span s{ptr, len};
s.subspan(1, 2) 得到中间两个元素std::span 本身不防止悬空(dangling)——它不延长所指对象的生命周期,传入已销毁的 vector.data() 仍是未定义行为。但它提供了一些安全辅助:
s.data() 和 s.size() 明确暴露底层信息s[i] 不做越界检查(和原生数组一样快),但调试模式下部分标准库实现(如 MSVC 的 /std:c++20 + _ITERATOR_DEBUG_LEVEL=2)会触发断言std::span::at(i) 可手动做带异常的越界检查(抛 std::out_of_range)std::vector 构造(因它不是真正连续存储),也禁止从 const 容器构造非 const spanstd::span 特别适合函数接口设计:
void func(int* p, size_t n),写成 void func(std::span data) ,语义清晰、调用安全、支持所有连续容器std::sort(s.begin(), s.end()) 或 range-v3 算法基本上就这些。它不复杂,但容易忽略——一旦习惯用 span 替代裸指针传数组,代码会立刻变得更健壮、更易读、更泛化。