span
std::span 是 C++20 引入的轻量级只读(或可读写)视图,表示一段连续内存区间。它本质上是一个指针 + 长度,不拥有数据,拷贝极轻量。
核心价值:用一个 span<T> 参数代替 T* ptr + size_t len 对,或代替 const std::vector<T>&(后者绑定了容器类型)。
头文件与基本特征
#include <span>
| 特征 | 说明 |
|---|---|
| 所有权 | 不拥有数据,只是"借用" |
| 内存 | 连续区间 |
| 编译期长度 | 可选(span<T, N> 为固定长度视图) |
| 替代 | T* + size、const vector<T>&(仅读时) |
基本用法
#include <iostream>
#include <span>
#include <vector>
void print(std::span<const int> data) {
for (int x : data) {
std::cout << x << ' ';
}
std::cout << '\n';
}
int main() {
int arr[] = {1, 2, 3, 4, 5};
std::vector<int> v = {10, 20, 30};
print(arr); // 从 C 数组
print(v); // 从 vector
print(v.data(), 2); // 从指针 + 长度
return 0;
}
同一个函数,接受数组、vector、指针+长度——无需重载。
子区间(零拷贝切片)
std::span<int> full = arr;
std::span<int> first3 = full.first(3); // 前 3 个
std::span<int> last2 = full.last(2); // 后 2 个
std::span<int> sub = full.subspan(1, 3); // 从索引 1 开始 3 个
全是零拷贝,只是调整了指针和长度。
常用接口
| 接口 | 作用 |
|---|---|
data() | 获取底层指针 |
size() / size_bytes() | 元素数 / 字节数 |
empty() | 是否为空 |
operator[] | 索引访问 |
begin() / end() | 迭代器 |
first(n) / last(n) | 前后切片 |
subspan(offset, count) | 中间切片 |
使用注意
span不拥有数据,被引用的数据必须比span活得久。- 通常传值即可(拷贝只是两个指针),不需要传
const span&。 span<T>可读写,span<const T>只读。- 它替代
const vector<T>&做只读参数,接口更泛化且不绑定容器类型。
小结
std::span 让"传一段连续数组"的接口变得通用而轻量。遇到只读数组参数时,优先用 span<const T> 而不是 const vector<T>&。