span 类(C++ 标准库)

提供连续对象序列的轻量级视图。 span 提供了一种安全的方法来对在内存中背靠背排列的对象进行迭代和索引。 例如存储在内置数组中的对象 std::arraystd::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 元素的类型,没有 constvolatile 限定。
构造函数 描述
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 成员函数都具有恒定的时间复杂度。

arrayvector不同,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。 仅当模板参数 Extent0dynamic_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。 仅当模板参数 Extentdynamic_extent 或等于 N 时在重载解析期间考虑。
span(R&& r) 从一个范围构造一个 span。 仅在模板参数 Extent 不是 dynamic_extent 时才参与重载决议。
span(const span& other) 编译器生成的构造函数。 数据指针的浅拷贝是安全的,因为 span 不会分配内存来保存元素。
span(const span<OtherElementType, OtherExtent>& s) noexcept; 转换构造函数:从另一个 span 构造一个 span。 仅当模板参数 Extentdynamic_extentNdynamic_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
要放入子跨度的元素数量。 如果 countdynamic_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 中元素的类型,没有 constvolatile 限定。

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>>>;

另请参阅

<span>
如何使用类模板参数推导