span提供了对连续对象序列的视图,它是一个轻量级的、非拥有式的类模板。
template<
class T,
std::size_t Extent = std::dynamic_extent
> class span;
本文章的代码库:
https://gitee.com/gamestorm577/CppStd
成员函数
构造、析构和赋值
构造函数
可以用迭代器、数组、初始化列表等来构造一个span。代码示例:
std::vector<float> vec(20, 1.f);
float arr1[] = {1.f, 2.f, 3.f};
std::array<float, 4> arr2 = {1.f, 2.f, 3.f, 4.f};
std::span<float> s1(vec.begin(), 5);
std::span<float> s2(vec.begin(), vec.begin() + 2);
std::span<float> s3(arr1);
std::span<float> s4(arr2);
std::span<const float> s5({1.f, 2.f, 3.f});
std::cout << "s1 size = " << s1.size() << std::endl;
std::cout << "s2 size = " << s2.size() << std::endl;
std::cout << "s3 size = " << s3.size() << std::endl;
std::cout << "s4 size = " << s4.size() << std::endl;
std::cout << "s5 size = " << s5.size() << std::endl;
输出结果:
s1 size = 5
s2 size = 2
s3 size = 3
s4 size = 4
s5 size = 3
析构函数
span并不拥有对象,当span析构时,其管理的对象并不会被删除。代码示例:
struct MyStruct
{
~MyStruct()
{
std::cout << "MyStruct destruct\n";
}
};
std::array<MyStruct, 3> arr;
{
std::span<MyStruct> s(arr);
std::cout << "span scope about to end" << std::endl;
}
std::cout << "span scope end" << std::endl;
输出结果:
span scope about to end
span scope end
MyStruct destruct
MyStruct destruct
MyStruct destruct
赋值函数
可以用另一个span给span赋值。代码示例:
std::span<const float> s1({1.f, 2.f, 3.f});
std::span<const float> s2;
s2 = s1;
std::cout << "s1 size = " << s1.size() << std::endl;
std::cout << "s2 size = " << s2.size() << std::endl;
输出结果:
s1 size = 3
s2 size = 3
迭代器
接口begin、cbegin指向span起始的迭代器,end、cend指向末尾的迭代器。rbegin、crbegin指向起始的逆向迭代器,rend、crend指向末尾的逆向迭代器。代码示例:
std::vector<float> vec{1.1f, 2.1f, 3.1f, 4.1f};
std::span<float> s(vec.begin(), vec.begin() + 2);
for (auto iter = s.begin(); iter != s.end(); ++iter)
{
*iter += 10;
}
for (auto i : s)
{
std::cout << i << " ";
}
std::cout << std::endl;
for (auto i : vec)
{
std::cout << i << " ";
}
std::cout << std::endl;
输出结果:
11.1 12.1
11.1 12.1 3.1 4.1
元素访问
front
返回第一个元素的引用。代码示例:
std::vector<float> vec{1.1f, 2.1f, 3.1f, 4.1f};
std::span<float> s(vec);
s.front() += 20;
std::cout << "s front: " << s.front() << std::endl;
输出结果:
s front: 21.1
back
返回最后一个元素的引用。代码示例:
std::vector<float> vec{1.1f, 2.1f, 3.1f, 4.1f};
std::span<float> s(vec);
s.back() += 20;
std::cout << "s back: " << s.back() << std::endl;
输出结果:
s back: 24.1
operator[]
返回指定索引的元素的引用。代码示例:
std::vector<float> vec{1.1f, 2.1f, 3.1f, 4.1f};
std::span<float> s(vec);
s[2] += 30;
std::cout << "s at 2 is: " << s[2] << std::endl;
输出结果:
s at 2 is: 33.1
data
获取对象序列的起始指针。代码示例:
std::vector<float> vec{1.1f, 2.1f, 3.1f, 4.1f};
std::span<float> s(vec);
float* data = s.data();
std::cout << "num is: " << *data << std::endl;
输出结果:
num is: 1.1
观察器
size
获取元素的个数。代码示例:
std::vector<float> vec{1.1f, 2.1f, 3.1f, 4.1f};
std::span<float> s(vec);
std::cout << "s size = " << s.size() << std::endl;
输出结果:
s size = 4
size_bytes
获取元素的字节大小。代码示例:
std::vector<float> vec{1.1f, 2.1f, 3.1f, 4.1f};
std::span<float> s(vec);
std::cout << "s size_bytes = " << s.size_bytes() << std::endl;
输出结果:
s size_bytes = 16
empty
检查span是否为空。代码示例:
std::vector<float> vec{1.1f, 2.1f, 3.1f, 4.1f};
std::span<float> s1(vec);
std::span<float> s2;
std::cout << std::boolalpha;
std::cout << "s1 empty = " << s1.empty() << std::endl;
std::cout << "s2 empty = " << s2.empty() << std::endl;
输出结果:
s1 empty = false
s2 empty = true
子视图
first
获取span的前n个子列。代码示例:
std::vector<float> vec{1.1f, 2.1f, 3.1f, 4.1f};
std::span<float> s1(vec);
std::span<float, 3> s2 = s1.first<3>();
std::span<float, std::dynamic_extent> s3 = s1.first(2);
std::cout << "s1 size = " << s1.size() << std::endl;
std::cout << "s2 size = " << s2.size() << std::endl;
std::cout << "s3 size = " << s3.size() << std::endl;
输出结果:
s1 size = 4
s2 size = 3
s3 size = 2
last
获取span的后n个子列。代码示例:
std::vector<float> vec{1.1f, 2.1f, 3.1f, 4.1f};
std::span<float> s1(vec);
std::span<float, 3> s2 = s1.last<3>();
std::span<float, std::dynamic_extent> s3 = s1.last(2);
std::cout << "s2 front = " << s2.front() << std::endl;
std::cout << "s3 front = " << s3.front() << std::endl;
输出结果:
s2 front = 2.1
s3 front = 3.1
subspan
获取某个区间的子段。代码示例:
std::vector<float> vec{1.1f, 2.1f, 3.1f, 4.1f};
std::span<float> s1(vec);
std::span<float, 3> s2 = s1.subspan<1, 3>();
std::span<float, std::dynamic_extent> s3 = s1.subspan(2, 2);
std::cout << "s2 front = " << s2.front() << std::endl;
std::cout << "s3 front = " << s3.front() << std::endl;
输出结果:
s2 front = 2.1
s3 front = 3.1
非成员函数
as_bytes、as_writable_bytes
获取序列的byte视图。代码示例:
std::vector<int> vec{1, 2, 3, 4};
std::span<int> s1(vec);
std::span<const std::byte, std::dynamic_extent> s2 = std::as_bytes(s1);
std::cout << "s2 size = " << s2.size() << std::endl;
输出结果:
s2 size = 16