std::span 是 C++20 标准库新增的一个轻量级容器视图(view),它不拥有数据,而是提供对已有连续内存块(如数组、std::vector、std::array 等)的只读或可写访问。通过使用 std::span,程序员可以在不拷贝元素的前提下,将一段连续数据作为参数传递给函数,提升性能与可读性。本文将从定义、用法、优势、边界检查以及常见陷阱等方面,系统性地剖析 std::span 的使用技巧。
1. std::span 的定义与基础语义
template<class ElementType, std::size_t Extent = std::dynamic_extent>
class span;
- ElementType:元素类型,决定访问时的类型;
- Extent:已知长度的模板参数,若未知则使用
std::dynamic_extent,即动态长度。
构造函数支持多种来源:
- `span s = {1, 2, 3, 4, 5};`(由初始值列表构造)
- `span s = vec;`(从 `std::vector` 自动推导)
- `span s = std::array;`
- `span s = std::string_view(someString);`
2. 只读 vs 可写
span<const int> rs = vec; // 只读
span <int> ws = vec; // 可写
只读视图禁止修改元素,适合安全传递数据;可写视图可以在函数内部修改底层容器,但必须保证底层容器存在且不发生移动。
3. 访问方式
s.size():元素数量。s.empty():是否为空。s.front() / s.back():首尾元素。s[n]:随机访问(与数组相同)。s.begin() / s.end():迭代器。s.subspan(offset, count):返回子视图,类似std::string_view::substr。s.first(count)/s.last(count):取前/后若干元素。
4. 典型使用场景
4.1 函数参数化
void sortRange(span <int> data) {
std::sort(data.begin(), data.end());
}
无论传入 int[10]、`std::vector