span
类(C++ 标准库)
提供连续对象序列的轻量级视图。 span
提供了一种安全的方法来对在内存中背靠背排列的对象进行迭代和索引。 例如存储在内置数组中的对象 std::array
或 std::vector
。
如果你通常使用指针和索引访问一系列背靠背对象,则 span
是一种更安全、轻量级的替代方案。
要设置 span
的大小,可以在编译时通过将大小指定为模板参数,也可以在运行时指定 dynamic_extent
。
语法
template<class T, size_t Extent = dynamic_extent>
class span;
模板参数
T
span
中元素的类型。
Extent
span
中的元素数量(如果在编译时指定)。 如果元素的数量将在运行时指定,则为 std::dynamic_extent
。
成员
类型定义 | 描述 |
---|---|
const_pointer |
指向 const 元素的指针的类型。 |
const_reference |
const 元素的引用的类型。 |
difference_type |
两个元素间的带符号距离的类型。 |
element_type |
span 元素的类型。 |
iterator |
span 的迭代器类型。 |
pointer |
指向元素的指针的类型。 |
reference |
元素的引用的类型。 |
reverse_iterator |
span 的反向迭代器类型。 |
size_type |
span 中两个元素之间的无符号距离结果的类型。 |
value_type |
元素的类型,没有 const 或 volatile 限定。 |
构造函数 | 描述 |
span |
构造 span 。 |
迭代器支持 | 描述 |
begin |
获取指向 span 中第一个元素的迭代器。 |
end |
获取指向 span 末尾的迭代器。 |
rbegin |
获取指向 span 的最后一个元素的反向迭代器;即 span 反向后的开始。 |
rend |
获取指向 span 前面的反向迭代器;即 span 反向后的结尾。 |
访问元素 | 描述 |
back |
获取 span 中的最后一个元素。 |
data |
获取 span 中第一个元素的地址。 |
front |
获取 span 中的第一个元素。 |
operator[] |
访问指定位置处的元素。 |
观察程序 | 描述 |
empty |
测试 span 是否为空。 |
size |
获取 span 中的元素数。 |
size_bytes |
获取 span 的大小(以字节为单位)。 |
子视图 | 描述 |
first |
从 span 的前面获取一个子跨度。 |
last |
从 span 的后面获取一个子跨度。 |
subspan |
从 span 中的任意位置获取一个子跨度。 |
运算符 | 描述 |
span::operator= |
替换 span 。 |
span::operator[] |
获取指定位置的元素。 |
备注
所有 span
成员函数都具有恒定的时间复杂度。
与 array
或 vector
不同,span
不能“拥有”其内部的元素。 span
不会为其中的项目释放任何存储空间,因为它不拥有这些对象的存储空间。
要求
标头: <span>
(自C++20以来)
命名空间:std
编译器选项:/std:c++20
或更高版本是必需的。
span::back
获取 span
中的最后一个元素。
constexpr reference back() const noexcept;
返回值
对 span
中最后一个元素的引用。
示例
#include <span>
#include <iostream>
using namespace std;
int main()
{
int a[] = { 0,1,2 };
span<int> mySpan(a);
cout << mySpan.back();
}
2
span::begin
获取指向 span
中第一个元素的迭代器。
constexpr iterator begin() const noexcept;
返回值
指向 span
中的第一个元素的迭代器。
示例
#include <span>
#include <iostream>
using namespace std;
int main()
{
int a[] = { 0,1,2 };
span<int> mySpan(a);
auto i = mySpan.begin();
cout << *i;
}
0
span::data
获取指向 span
数据开头的指针。
constexpr pointer data() const noexcept;
返回值
指向 span
中的第一项的指针。
示例
#include <span>
#include <iostream>
using namespace std;
int main()
{
int a[] = { 0,1,2 };
span<int> mySpan(a);
auto i = mySpan.data();
cout << *i;
}
0
span::difference_type
span
中两个元素之间的元素数。
using difference_type = std::ptrdiff_t;
示例
#include <span>
#include <iostream>
int main()
{
int a[] = { 0,1,2 };
span<int> mySpan(a);
span<int>::difference_type distance = mySpan.end() - mySpan.begin();
cout << distance << std::endl;
}
3
span::element_type
span
中元素的类型。
using element_type = T;
备注
该类型是在创建 span
时从模板参数 T
中获取的。
示例
#include <span>
#include <iostream>
using namespace std;
int main()
{
int a[] = { 0,1,2 };
span<int> mySpan(a);
span<int>::element_type et = mySpan[2];
cout << et << endl;
}
2
span::empty
span
是否包含元素。
constexpr bool empty() const noexcept;
返回值
如果为 this->size() == 0
,则返回 true
。 否则为 false
。
示例
#include <span>
#include <iostream>
using namespace std;
int main()
{
int a[] = { 0,1,2 };
span<int> mySpan(a);
bool isEmpty = mySpan.empty(); // isEmpty == false
}
span::end
获取指向 span
结尾的迭代器。
constexpr iterator end() const noexcept;
返回值
一个迭代器,指向刚超出 span
末尾的位置。
备注
end
用于测试迭代器是否超过了其范围的末尾。
不要取消引用此迭代器返回的值。 用于标识迭代器是否已超出 span
中的最后一个元素。
示例
// Iteration
for (auto it = s1.begin(); it != s1.end(); ++it)
{
cout << *it;
}
span::first
获取一个子跨度,取自该 span
的前面。
constexpr auto first(size_type count) const noexcept;
template <size_t count> constexpr auto first() const noexcept;
参数
count
位于此 span
前面且要要放入子跨度的元素数。
元素的数量被指定为模板或函数的参数,如下所示。
返回值
span
,包含位于此 span
前面的 count
元素。
注解
尽可能使用此函数的模板版本在编译时验证 count
,并保留有关 span
的信息,因为它返回固定范围的 span
。
示例
#include <span>
#include <iostream>
using namespace std;
int main()
{
int a[] = { 0,1,2 };
span<int> mySpan(a);
auto first2 = mySpan.first(2);
cout << "mySpan.first(2): ";
for (auto& i : first2)
{
cout << i;
}
cout << "\nmySpan.first<2>: ";
auto viewSpan = mySpan.first<2>();
for (auto& i : viewSpan)
{
cout << i;
}
}
mySpan.first(2): 01
mySpan.first<2>: 01
span::front
获取 span
中的第一个元素。
constexpr reference front() const noexcept;
返回值
对 span
中第一个元素的引用。
示例
#include <span>
#include <iostream>
using namespace std;
int main()
{
int a[] = { 0,1,2 };
span<int> mySpan(a);
auto i = mySpan.front();
cout << i;
}
0
span::iterator
基于 span
元素的 iterator
的类型。
using iterator = implementation-defined-iterator-type;
备注
这种类型用作基于 span
中元素的 iterator
。
示例
#include <span>
#include <iostream>
using namespace std;
int main()
{
int a[] = { 0,1,2 };
span<int> mySpan(a);
span<int>::iterator it = mySpan.begin();
cout << *it++ << *it++ << *it;
}
012
span::last
获取一个子跨度,取自该 span
的结尾。
constexpr span<element_type, dynamic_extent> last(const size_type count) const noexcept;
template <size_t count> constexpr span<element_type, count> last() const noexcept;
参数
count
位于此 span
结尾且要要放入子跨度的元素数。
数量可以被指定为模板或函数的参数,如下所示。
返回值
一个 span
,包含此 span
中的最后 count
个元素。
备注
尽可能使用此函数的模板版本在编译时验证 count
,并保留有关 span
的信息,因为它返回固定范围的 span
。
示例
#include <span>
#include <iostream>
using namespace std;
int main()
{
int a[] = { 0,1,2 };
span<int> mySpan(a);
auto first2 = mySpan.last(2);
cout << "mySpan.last(2): ";
for (auto& i : last2)
{
cout << i;
}
cout << "\nmySpan.last<2>: ";
auto viewSpan = mySpan.last<2>();
for (auto& i : viewSpan)
{
cout << i;
}
}
mySpan.last(2): 12
mySpan.last<2>: 12
span::operator[]
获取 span
中指定位置的元素。
constexpr reference operator[](size_type offset) const;
参数
offset
span
中要访问的元素(从零开始)。
返回值
对 offset
位置处元素的引用。 如果位置无效,则该行为未定义。
示例
#include <span>
#include <iostream>
using namespace std;
int main()
{
int a[] = { 0,1,2 };
span<int> mySpan(a);
cout << mySpan[1];
}
1
span::operator=
将另一个span
分配给此 span。
constexpr span& operator=(const span& other) noexcept = default;
参数
other
分配给此 span 的 span
。
返回值
*this
注解
赋值对数据指针和大小进行浅拷贝。 浅拷贝是安全的,因为 span
不会为其包含的元素分配内存。
示例
#include <span>
#include <iostream>
using namespace std;
int main()
{
int a[] = { 0,1,2 };
span<int> mySpan(a);
span<int> mySpan2;
mySpan2 = mySpan;
for (auto &i : mySpan2)
{
cout << it;
}
}
012
span::pointer
指针的类型,是 const
指针,指向 span
元素。
using pointer = T*;
using const_pointer = const T*;
示例
#include <span>
#include <iostream>
using namespace std;
int main()
{
int a[] = { 0,1,2 };
span<int> mySpan(a);
// pointer
span<int>::pointer ptr = &mySpan[2];
*ptr = 9;
cout << mySpan[2];
// const pointer
span<int>::const_pointer cPtr = &mySpan[0];
// *cPtr = 9; error - const
cout << *cPtr;
}
90
span::rbegin
获取指向此 span
的最后一个元素的反向迭代器。
constexpr reverse_iterator rbegin() const noexcept;
返回值
指向逆向 span
开头的迭代器。
示例
#include <span>
#include <iostream>
using namespace std;
int main()
{
int a[] = { 0,1,2 };
span<int> mySpan(a);
for (auto rIt = s1.rbegin(); rIt != s1.rend(); ++rIt)
{
cout << *rIt;
}
}
210
span::reference
引用的类型,一个对 span
元素的 const
引用。
using reference = T&;
using const_reference = const T&;
示例
#include <span>
#include <iostream>
using namespace std;
int main()
{
int a[] = { 0,1,2 };
span<int> mySpan(a);
// reference
span<int>::reference ref = mySpan[0];
ref = 9;
cout << mySpan[0];
// const reference
span<int>::const_reference cRef = mySpan[1];
// cRef = 9; error because const
cout << cRef;
}
91
span::rend
获取刚超出逆向 span
的末尾位置的随机访问迭代器。
constexpr reverse_iterator rend() const noexcept;
返回值
在反向 span
中的最后一个元素之后的占位符的反向迭代器;即未反转的 span
中第一个元素之前的占位符。
备注
rend
用于反向 span
,正如 span::end
用于 span
一样。 可用于测试反向迭代器是否已到达其 span
的末尾。
不应对 rend
返回的值取消引用。
示例
#include <span>
#include <iostream>
using namespace std;
int main()
{
int a[] = { 0,1,2 };
span<int> mySpan(a);
for (auto rIt = s1.rbegin(); rIt != s1.rend(); ++rIt)
{
cout << *rIt;
}
}
span::reverse_iterator
span
的反向迭代器类型。
using reverse_iterator = std::reverse_iterator<iterator>;
示例
#include <span>
#include <iostream>
int main()
{
int a[] = { 0,1,2 };
span<int> mySpan(a);
span<int>::reverse_iterator rIt = mySpan.rbegin();
cout << *rIt++ << *rIt++ << *rIt;
}
210
span::size
获取 span
中的元素数。
constexpr size_t size() const noexcept;
返回值
span
中的元素的数量。
示例
#include <span>
#include <iostream>
using namespace std;
int main()
{
int a[] = { 0,1,2 };
span<int> mySpan(a);
cout << mySpan.size();
}
3
span::size_bytes
获取 span
中元素的大小(以字节为单位)。
constexpr size_type size_bytes() const noexcept;
返回值
span
中所有元素占用的字节数;即 sizeof(element_type)
乘以 span
中的元素个数。
示例
#include <span>
#include <iostream>
using namespace std;
int main()
{
int a[] = { 0,1,2 };
span<int> mySpan(a);
cout << mySpan.size_bytes(); // 3 elements * 4 (size of an int)
}
12
span::size_type
无符号类型,适合存储 span
中的元素个数。
using size_type = size_t;
示例
#include <span>
#include <iostream>
using namespace std;
int main()
{
int a[] = { 0,1,2 };
span<int> mySpan(a);
span<int>::size_type szType = mySpan.size();
cout << szType;
}
3
span::span
span
构造函数。
constexpr span() noexcept
requires (Extent == 0 || Extent == dynamic_extent) = default;
template <class It>
constexpr explicit(Extent != dynamic_extent)
span(It first, size_type count) noexcept
template <class It, class End>
constexpr explicit(Extent != dynamic_extent)
span(It first, End last) noexcept(noexcept(last - first))
template <class T, size_t N>
requires (Extent == dynamic_extent || Extent == N) && is_convertible_v<T (*)[], T (*)[]>
constexpr span(array<T, N>& arr) noexcept
template <class T, size_t N>
requires (Extent == dynamic_extent || Extent == N) && is_convertible_v<const T (*)[], T (*)[]>
constexpr span(const array<T, N>& arr) noexcept
template <size_t N>
requires (Extent == dynamic_extent || Extent == N)
constexpr span(type_identity_t<T> (&arr)[N]) noexcept
template <class R>
constexpr explicit(Extent != dynamic_extent)
span(R&& r)
// default copy ctor
constexpr span(const span& other) noexcept = default;
// converting ctor
template <class T, size_t OtherExtent>
requires (Extent == dynamic_extent || OtherExtent == dynamic_extent ||
Extent == OtherExtent) && is_convertible_v<T (*)[], T (*)[]>
constexpr explicit(Extent != dynamic_extent && OtherExtent == dynamic_extent)
span(const span<T, OtherExtent>& other) noexcept
参数
arr
从数组构造一个 span
。
count
将位于 span
中的元素数。
first
指向 span
中第一个元素的迭代器。
last
迭代器,指向刚刚经过 span
中的最后一个元素。
N
span
中的元素数量。
other
复制此 span
。
r
从 R
范围构造一个 span
。
备注
span
不会为 span
中的项目释放存储空间,因为它不拥有其中对象的存储空间。
构造函数 | 说明 |
---|---|
span() |
构造一个空的 span 。 仅当模板参数 Extent 是 0 或 dynamic_extent 时在重载解析期间才会考虑。 |
span(It first, size_type count) |
从迭代器 first 的前 count 个元素构造一个 span 。 仅当模板参数 Extent 不是 dynamic_extent 时在重载解析期间才会考虑。 |
span(It first, End last) |
从迭代器 first 中的元素构造一个 span ,直到到达 last 结尾。 仅当模板参数 Extent 不是 dynamic_extent 时在重载解析期间才会考虑。 It 必须是 contiguous_iterator 。 |
span(array<T, N>& arr) noexcept; span(const array<T, N>& arr) noexcept; span(type_identity_t<element_type> (&arr)[N]) noexcept; |
从指定数组的 N 元素构造一个 span 。 仅当模板参数 Extent 为 dynamic_extent 或等于 N 时在重载解析期间考虑。 |
span(R&& r) |
从一个范围构造一个 span 。 仅在模板参数 Extent 不是 dynamic_extent 时才参与重载决议。 |
span(const span& other) |
编译器生成的构造函数。 数据指针的浅拷贝是安全的,因为 span 不会分配内存来保存元素。 |
span(const span<OtherElementType, OtherExtent>& s) noexcept; |
转换构造函数:从另一个 span 构造一个 span 。 仅当模板参数 Extent 为 dynamic_extent 或 N 为 dynamic_extent 或等于 Extent 时才参与重载解析。 |
示例
#include <span>
using namespace std;
int main()
{
const int MAX=10;
int x[MAX];
for (int i = 0; i < MAX; i++)
{
x[i] = i;
}
span<int, MAX> span1{ x }; // fixed-size span: compiler error if size of x doesn't match template argument MAX
span<int> span2{ x }; // size is inferred from x
span<const int> span3 = span2; // converting constructor
span<int> span4( span2 ); // copy constructor
}
span::subspan
获取此 span
的一个子跨度。
constexpr auto subspan(size_type offset, size_type count = dynamic_extent) const noexcept;
template <size_t offset, size_t count = dynamic_extent>
constexpr auto subspan() const noexcept
参数
count
要放入子跨度的元素数量。 如果 count
为 dynamic_extent
(默认值),则子跨度获取方式是从 offset
直至 span
的结尾。
offset
此 span
中开始子跨度的位置。
返回值
在此 span
中,从 offset
开始的 span
。 包含 count
元素。
注解
该函数的模板版本可以在编译时检查计数,即,通过返回固定范围的 span
来保留有关 span
的信息。
示例
#include <span>
#include <iostream>
using namespace std;
int main()
{
int a[] = { 0,1,2 };
span<int> mySpan(a);
cout << "mySpan.subspan(1,2): ";
for (auto& i : mySpan.subspan(1,2))
{
cout << i;
}
cout << "\nmySpan.subspan<1,2>: ";
for (auto& i : mySpan.subspan<1,2>())
{
cout << i;
}
cout << "\nmySpan.subspan<1>: ";
for (auto& i : mySpan.subspan<1>)
{
cout << i;
}
}
mySpan.subspan(1,2): 12
mySpan.subspan<1,2>: 12
mySpan.subspan<1>: 12
span::value_type
span
中元素的类型,没有 const
或 volatile
限定。
using value_type = std::remove_cv_t<T>;
示例
#include <span>
#include <iostream>
using namespace std;
int main()
{
int a[] = { 0,1,2 };
span<int> mySpan(a);
span<int>::value_type vType = mySpan[2];
cout << vType;
}
2
推导指南
针对 span
提供以下推导指南。
// Allows the extent to be deduced from std::array and C++ built-in arrays
template <class T, size_t Extent>
span(T (&)[Extent]) -> span<T, Extent>;
template <class T, size_t Size>
span(array<T, Size>&) -> span<T, Size>;
template <class T, size_t Size>
span(const array<T, Size>&) -> span<const T, Size>;
// Allows the element type to be deduced from the iterator and the end of the span.
// The iterator must be contiguous
template <contiguous_iterator It, class End>
span(It, End) -> span<remove_reference_t<iter_reference_t<It>>>;
// Allows the element type to be deduced from a range.
// The range must be contiguous
template <ranges::contiguous_range Rng>
span(Rng &&) -> span<remove_reference_t<ranges::range_reference_t<Rng>>>;