微信小程序|基于小程序+云开发制作一个菜谱小程序
文/依依
2023-03-14
1645次浏览

文章摘要:span 是 C++20 中引入的一个新的标准容器,它用于表示连续的一段内存区间,类似于一个轻量级的只读数组容器。
span 是一个轻量级的非拥有式容器,它提供了对连续内存的引用。 span 的主要用途是作为函数参数,可以避免不必要的内存拷贝,并且可以防止悬垂指针和空指针引用的问
一.span容器
span 是 C++20 中引入的一个新的标准容器,它用于表示连续的一段内存区间,类似于一个轻量级的只读数组容器。
span 是一个轻量级的非拥有式容器,它提供了对连续内存的引用。 span 的主要用途是作为函数参数,可以避免不必要的内存拷贝,并且可以防止悬垂指针和空指针引用的问题。
它的定义在头文件 中,并位于 std 命名空间中。span 包含了一个指向连续内存区域的指针以及它所占用的大小,可以通过它来访问这个内存区域中的元素。
span 主要用于以下场景:
作为函数的参数,用于指示函数需要处理的数据范围;
作为类的成员变量,用于表示对象所管理的内存区域;
作为数组的视图,用于访问数组的一部分
二.span的用法
下面是几种 span 的用法示例:
1.将数组转换为 span:
int arr[] = {1, 2, 3, 4, 5};
spans(arr, 5);
这里将一个整型数组 arr 转换为 span 类型,并使用数组首地址和元素个数作为参数。
2.使用 span 来遍历一个容器:
vectorvec = {1, 2, 3, 4, 5};
for (auto&& x : span(vec)) {
cout << x << " ";
}
这里使用 span(vec) 来构造一个 span 对象,遍历其中的元素并输出。
3.使用 span 来获取子序列:
int arr[] = {1, 2, 3, 4, 5};
spans(arr, 5);
auto s1 = s.subspan(1, 3);
这里将一个 span 对象 s 分割为从第 1 个元素开始,长度为 3 的子序列,并将结果存储到 s1 中。
4.将 span 转换为其他容器类型:
int arr[] = {1, 2, 3, 4, 5};
spans(arr, 5);
vectorvec(s.begin(), s.end());
这里使用 s.begin() 和 s.end() 将 span 对象 s 转换为迭代器范围,并使用这个迭代器范围构造一个 vector 容器 vec。
三.span的底层原理
下面为 span的简化版源码,用于展示其基本实现:
template
class span {
public:
// 定义迭代器类型
using iterator = T*;
using const_iterator = const T*;
// 构造函数
constexpr span() noexcept : data_(nullptr), size_(0) {}
constexpr span(T* ptr, std::size_t count) : data_(ptr), size_(count) {}
template
constexpr span(T(&arr)[N]) noexcept : data_(arr), size_(N) {}
template
constexpr span(Container& c) noexcept : data_(c.data()), size_(c.size()) {}
// 拷贝构造函数和拷贝赋值运算符
constexpr span(const span& other) noexcept = default;
span& operator=(const span& other) noexcept = default;
// 访问元素和迭代器操作
constexpr T* data() const noexcept { return data_; }
constexpr std::size_t size() const noexcept { return size_; }
constexpr bool empty() const noexcept { return size_ == 0; }
constexpr T& operator[](std::size_t idx) const { return data_[idx]; }
constexpr T& front() const { return data_[0]; }
constexpr T& back() const { return data_[size_-1]; }
constexpr iterator begin() const noexcept { return data_; }
constexpr iterator end() const noexcept { return data_ + size_; }
constexpr const_iterator cbegin() const noexcept { return data_; }
constexpr const_iterator cend() const noexcept { return data_ + size_; }
private:
T* data_; // 元素指针
std::size_t size_; // 元素数量
};

span 是 C++20 中引入的一个新的标准容器,它用于表示连续的一段内存区间,类似于一个轻量级的只读数组容器。
span 是一个轻量级的非拥有式容器,它提供了对连续内存的引用。 span 的主要用途是作为函数参数,可以避免不必要的内存拷贝,并且可以防止悬垂指针和空指针引用的问题。
它的定义在头文件 中,并位于 std 命名空间中。span 包含了一个指向连续内存区域的指针以及它所占用的大小,可以通过它来访问这个内存区域中的元素。
span 主要用于以下场景:
作为函数的参数,用于指示函数需要处理的数据范围;
作为类的成员变量,用于表示对象所管理的内存区域;
作为数组的视图,用于访问数组的一部分
二.span的用法
下面是几种 span 的用法示例:
1.将数组转换为 span:
int arr[] = {1, 2, 3, 4, 5};
spans(arr, 5);
这里将一个整型数组 arr 转换为 span 类型,并使用数组首地址和元素个数作为参数。
2.使用 span 来遍历一个容器:
vectorvec = {1, 2, 3, 4, 5};
for (auto&& x : span(vec)) {
cout << x << " ";
}
这里使用 span(vec) 来构造一个 span 对象,遍历其中的元素并输出。
3.使用 span 来获取子序列:
int arr[] = {1, 2, 3, 4, 5};
spans(arr, 5);
auto s1 = s.subspan(1, 3);
这里将一个 span 对象 s 分割为从第 1 个元素开始,长度为 3 的子序列,并将结果存储到 s1 中。
4.将 span 转换为其他容器类型:
int arr[] = {1, 2, 3, 4, 5};
spans(arr, 5);
vectorvec(s.begin(), s.end());
这里使用 s.begin() 和 s.end() 将 span 对象 s 转换为迭代器范围,并使用这个迭代器范围构造一个 vector 容器 vec。
三.span的底层原理
下面为 span的简化版源码,用于展示其基本实现:
template
class span {
public:
// 定义迭代器类型
using iterator = T*;
using const_iterator = const T*;
// 构造函数
constexpr span() noexcept : data_(nullptr), size_(0) {}
constexpr span(T* ptr, std::size_t count) : data_(ptr), size_(count) {}
template
constexpr span(T(&arr)[N]) noexcept : data_(arr), size_(N) {}
template
constexpr span(Container& c) noexcept : data_(c.data()), size_(c.size()) {}
// 拷贝构造函数和拷贝赋值运算符
constexpr span(const span& other) noexcept = default;
span& operator=(const span& other) noexcept = default;
// 访问元素和迭代器操作
constexpr T* data() const noexcept { return data_; }
constexpr std::size_t size() const noexcept { return size_; }
constexpr bool empty() const noexcept { return size_ == 0; }
constexpr T& operator[](std::size_t idx) const { return data_[idx]; }
constexpr T& front() const { return data_[0]; }
constexpr T& back() const { return data_[size_-1]; }
constexpr iterator begin() const noexcept { return data_; }
constexpr iterator end() const noexcept { return data_ + size_; }
constexpr const_iterator cbegin() const noexcept { return data_; }
constexpr const_iterator cend() const noexcept { return data_ + size_; }
private:
T* data_; // 元素指针
std::size_t size_; // 元素数量
};

相关内容推荐