在 C++20 中,std::span 提供了一种轻量级的、非拥有的视图,用于访问连续内存块。与传统的指针或数组不同,std::span 还可以与任何支持 begin()、end()、data() 和 size() 的容器互操作。下面我们通过几个例子来演示如何在不同容器之间快速、无拷贝地进行转换,以及如何利用 std::span 提升代码的灵活性和性能。
1. 直观的 span 对容器的包装
#include <iostream>
#include <vector>
#include <array>
#include <span>
void printSpan(const std::span <int>& s) {
for (int x : s) std::cout << x << ' ';
std::cout << '\n';
}
int main() {
std::vector <int> vec = {1, 2, 3, 4, 5};
std::array<int, 3> arr = {10, 20, 30};
// 直接从容器创建 span
std::span <int> sv = vec;
std::span <int> sa = arr;
printSpan(sv); // 输出: 1 2 3 4 5
printSpan(sa); // 输出: 10 20 30
}
在上述代码中,std::span 的构造函数可以接受任何支持连续内存的容器,自动推断长度。
2. 通过 data() 与 size() 手动构造
有时你需要对容器的子范围做视图:
std::vector <int> vec = {5, 10, 15, 20, 25, 30};
auto firstHalf = std::span <int>(vec.data(), vec.size() / 2);
auto secondHalf = std::span <int>(vec.data() + vec.size() / 2, vec.size() / 2);
printSpan(firstHalf); // 5 10 15
printSpan(secondHalf); // 20 25 30
使用 data() 指针和 size() 长度,可以在不复制数据的前提下切分视图。
3. 读写视图的区别
std::span 有两种形式:可读写的 `std::span