C++20:span

在C++20中,std::span是一个非拥有的对象引用,它可以看作是指针和长度的对,提供了对数组或其他连续内存的安全访问。std::span是一个轻量级的、非拥有的引用,它不负责管理其指向的数据的生命周期。这意味着,你不需要担心内存泄漏或是其他的内存管理问题。但是,你需要确保在使用span时,它引用的数据仍然是有效的。

std::span提供连续对象序列的轻量级视图。 span 提供了一种安全的方法来对在内存中背靠背排列的对象进行迭代和索引。 例如存储在内置数组中的对象 std::array 或 std::vector。如果你通常使用指针和索引访问一系列背靠背对象,则 span 是一种更安全、轻量级的替代方案。要设置 span 的大小,可以在编译时通过将大小指定为模板参数,也可以在运行时指定 dynamic_extent。

定义

std::span的定义如下:

template<class T, size_t Extent = dynamic_extent>
class span;

其中,T:span 中元素的类型。
Extent:span 中的元素数量(如果在编译时指定)。 如果元素的数量将在运行时指定,则为 std::dynamic_extent。

构造

std::span是一组连续内存的viewer而不是owner,所以需要在已存在的连续数组上构造,这个连续内存可以是c数组,带着大小的指针,或者std::string/std::array/std::vector等等。

span的几种构造方式如下:

    std::vector<int>vec1{1, 2, 3, 4, 5, 6};
    std::span<int>s1(vec1);
std::vector<int>vec2{11, 22, 33, 44, 55, 66};
std::span<int, 6>s2(vec2);
   std::vector<int>vec1{1, 2, 3, 4, 5, 6};
   std::span<int>s3(vec1.begin(), vec1.end());
  std::vector<int>vec1{1, 2, 3, 4, 5, 6};
  std::span<int>s4(vec1.begin() + 1, vec1.end());
  std::vector<int>vec1{1, 2, 3, 4, 5, 6};
  std::span<int>s5(vec1.begin(), 6);
int carray[5] = {1, 2, 3, 4, 5};
  int carray[5] = {1, 2, 3, 4, 5};
  std::span<int>s6(carray);
std::span sp2(s8.subspan(1, s8.size()-2));
    std::transform(s2.begin(), s2.end(), s2.begin(), [](int i) {
        return i*i;
    });

遍历

    std::vector<int>vec1{1, 2, 3, 4, 5, 6};
    std::span<int>s1(vec1);
  1. for循环遍历
    for(int i = 0; i < s1.size(); i++) {
        printf("%d, ", s1[i]);
    }
  1. 基于范围的for循环
    for(const auto item : s1) {
        printf("%d, ", item);
    } 
  1. 迭代器遍历
    for(auto iter = s1.begin(); iter != s1.end(); iter ++) {
        printf("%d, ", *iter);
    }

基于span实现一些方法

  1. 数组切片
template<class T, std::size_t N>
[[nodiscard]]
constexpr auto slide(std::span<T,N> s, std::size_t offset, std::size_t width)
{
    return s.subspan(offset, offset + width <= s.size() ? width : 0U);
}
  1. 数组前缀匹配
template<class T, std::size_t N, std::size_t M>
constexpr bool starts_with(std::span<T,N> data, std::span<T,M> prefix)
{
    return data.size() >= prefix.size()
        && std::equal(prefix.begin(), prefix.end(), data.begin());
}
  1. 数组后缀匹配
template<class T, std::size_t N, std::size_t M>
constexpr bool ends_with(std::span<T,N> data, std::span<T,M> suffix)
{
    return data.size() >= suffix.size()
        && std::equal(data.end() - suffix.size(), data.end(),
                      suffix.end() - suffix.size());
}
  1. 包含关系
template<class T, std::size_t N, std::size_t M>
constexpr bool contains(std::span<T,N> span, std::span<T,M> sub)
{
    return std::ranges::search(span, sub).begin() != span.end();
}

《C++ Primer》《Effective C++》是C++开发者必不可少的书籍,如果你想入门C++,以及想要精进C++开发技术,这两本书可以说必须要有。此外,《Linux高性能服务器编程》以及《Linux多线程服务端编程:使用muduo C++网络库》.(陈硕)》是快速提高你的linux开发能力的秘籍。《大话设计模式》可以增强我们的模型提取及设计能力,写出更优雅的代码。同时,《操作系统导论》更是开发必读书目,在网上搜索相关资源也要花费一些力气,需要的同学可以关注公众号【程序员DeRozan】,回复【1207】快速免费领取~

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Michael.Scofield

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值