C++20 std::span: 连续内存的轻量视图
请说明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>可变 vsspan<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_extent,s.size()返回运行时长度。s.first<3>()/s.last<3>()/s.subspan<1, 3>():编译期安全子区间。
使用场景:
- 函数参数:替代
(T* data, size_t len)或const vector<T>&(零拷贝,更通用)。 - 接口抽象:函数接受span,调用者可传数组、vector、std::array或raw指针+长度。
- 范围遍历:
for (auto& x : s)。
void process(std::span<int> data);
process(vec); // OK
process(arr); // OK
process({ptr, n}); // OK