string_view 是"字符的 view";span 是"任意类型的 view"。
解决什么问题?
// ❌ 传统函数签名:零散的指针+长度
void process(const float* data, size_t count);
// 调用者容易传错:process(arr, 1000) // 如果 arr 只有 500 个元素呢?
// ✅ span:长度自带
void process(std::span<const float> data);
// 调用者:process(arr); // 自动推导长度
// 或者:process(vec); // vector 也能直接传
span 的内存结构:
span<float> s(vec);
栈上占用 16 字节(64 位):
+──────────────────+──────────────────+
| ptr (8字节) | size (8字节) |
| 指向 vec.data() | vec.size() |
+──────────────────+──────────────────+
没有任何堆分配,不拥有数据,只是一个指针 + 长度。
什么时候用?
// 1. 替代 (T* data, size_t len) —— 最常见的场景
void process(std::span<const int> data);
// 2. 需要同时支持 vector / array / C 数组的函数
void sort_all(std::span<int> data) {
std::sort(data.begin(), data.end());
}
std::vector<int> v = {3, 1, 4, 1, 5};
int arr[] = {2, 7, 1, 8};
sort_all(v); // ✅ vector
sort_all(arr); // ✅ C 数组(自动推导长度为 4)
// 3. 子范围操作
auto first_half = s.first(s.size() / 2); // 取前半,不拷贝
auto second_half = s.last(s.size() / 2); // 取后半
auto middle = s.subspan(2, 5); // 取 [2, 7)
和 string_view 完全一样的生命周期规则
delete 原始数组后,span 悬垂。