容器库(17)-std::span

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

  • 5
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值