最近我收到了span<T>在我的代码中使用 ‘s 的建议,或者在使用 ‘s 的网站上看到了一些答案span——据说是某种容器。但是 - 我在 C++17 标准库中找不到类似的东西。
span<T>
span
那么这是什么神秘span<T>的,如果它是非标准的,为什么(或何时)使用它是一个好主意?
一个span<T>是:
T
struct { T * ptr; std::size_t length; }
它以前称为 anarray_view甚至更早于array_ref.
array_view
array_ref
一、什么时候 不 使用:
std::sort
std::find_if``std::copy
现在了解何时实际使用它:
当分配的长度或大小也很重要时,使用span<T>(分别span<const T>)而不是独立的T*(分别)。const T*因此,替换如下功能: void read_into(int* buffer, size_t buffer_size); 和: void read_into(span<int> buffer);
当分配的长度或大小也很重要时,使用span<T>(分别span<const T>)而不是独立的T*(分别)。const T*因此,替换如下功能:
span<const T>
T*
const T*
void read_into(int* buffer, size_t buffer_size);
和:
void read_into(span<int> buffer);
哦,跨度太棒了!使用span…
意味着您可以使用指针+长度/开始+结束指针组合,就像使用花哨的、拉皮条的标准库容器一样,例如:
for (auto& x : my_span) { /* do stuff */ }
std::find_if(my_span.cbegin(), my_span.cend(), some_predicate);
std::ranges::find_if(my_span, some_predicate);
…但绝对没有大多数容器类产生的开销。
int buffer[BUFFER_SIZE];
read_into(buffer, BUFFER_SIZE);
变成这样:
int buffer[BUFFER_SIZE]; read_into(buffer);
…这将做你想做的事。另见指南 P.5。
const vector<T>&当您希望数据在内存中连续时,是传递给函数的合理替代方法。再也不用被高大上的 C++ 大师骂了!
const vector<T>&
有助于静态分析,因此编译器可能能够帮助您捕获愚蠢的错误。
允许用于运行时边界检查的调试编译工具(即的方法将在…span中包含一些边界检查代码)#ifndef NDEBUG``#endif
#ifndef NDEBUG``#endif
表示您的代码(使用跨度)不拥有指向的内存。
使用spans 的动机甚至更多,您可以在C++ 核心指南中找到它- 但您会发现偏差。
编辑: 是的,std::span使用 C20 版本的语言添加到 C 中!
std::span
为什么只在 C++20 中?好吧,虽然这个想法并不新鲜——它目前的形式是与C++ 核心指南项目一起构思的,该项目在 2015 年才开始形成。所以花了一段时间。
它是核心指南的支持库 (GSL) 的一部分。实现:
gsl/span
GSL 实现通常假设一个实现 C++14 支持的平台 [ 11 ]。这些替代的单头实现不依赖于 GSL 设施:
martinmoene/span-lite
tcbrindle/span
请注意,这些不同的 span 实现在它们附带的方法/支持功能方面存在一些差异;它们也可能与 C++20 标准库中采用的版本有所不同。