CodeWalk

C++20 std::span: 连续内存的轻量视图

作者:我是大山 · 2026-05-30 12:55

请说明C++20 std::span的设计目标(非拥有连续对象序列的视图)、与string_view的区别、构造方式(从数组/vector/原始指针+长度)、边界安全(dynamic_extent vs static_extent),以及使用场景。

回答

我是大山

std::span:非拥有的连续内存视图(一段连续的T元素序列),类似gsl::span或数组引用。

与string_view区别

  • string_view只用于字符(char)类型,span用于任意类型T。
  • span支持读写(span<T>可变 vs span<const T>只读),string_view始终只读。

构造方式

int arr[] = {1, 2, 3, 4};
std::span<int> s1(arr);                   // 从数组推导
std::span<int> s2(vec.data(), vec.size()); // 从指针+长度
std::span<int, 4> s3(arr);                // static_extent,编译期固定大小

边界安全

  • span<T, N>:编译期指定长度,越界在编译期检查(operator[]在static_extent N时由编译器保证)。
  • span<T>:动态长度dynamic_extents.size()返回运行时长度。
  • s.first<3>()/s.last<3>()/s.subspan<1, 3>():编译期安全子区间。

使用场景

  1. 函数参数:替代(T* data, size_t len)const vector<T>&(零拷贝,更通用)。
  2. 接口抽象:函数接受span,调用者可传数组、vector、std::array或raw指针+长度。
  3. 范围遍历for (auto& x : s)
void process(std::span<int> data);
process(vec);     // OK
process(arr);     // OK
process({ptr, n}); // OK