什么是“跨度”?我什么时候应该使用一个? [英] What is a "span" and when should I use one?

查看:174
本文介绍了什么是“跨度”?我什么时候应该使用一个?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

最近我得到了在代码中使用 span< T> 的建议,或者在网站上看到了使用 span -应该是某种容器。但是-我在C ++ 17标准库中找不到类似的东西。

Recently I've gotten suggestions to use span<T>'s in my code, or have seen some answers here on the site which use span's - supposedly some kind of container. But - I can't find anything like that in the C++17 standard library.

那么这个神秘的 span< T> 是什么,以及为什么(或何时)

So what is this mysterious span<T>, and why (or when) is it a good idea to use it if it's non-standard?

推荐答案

是什么?



A span< T> 是:


  • a的非常轻量级的抽象内存中某个位置的 T 类型的连续值序列。

  • 基本上是结构{T * ptr; std :: size_t长度; } 和一堆便捷方法。

  • 非所有者类型(即引用类型 ,而不是值类型):它从不分配或取消分配任何东西,也不使智能指针保持活动状态。

  • A very lightweight abstraction of a contiguous sequence of values of type T somewhere in memory.
  • Basically a struct { T * ptr; std::size_t length; } with a bunch of convenience methods.
  • A non-owning type (i.e. a "reference-type" rather than a "value type"): It never allocates nor deallocates anything and does not keep smart pointers alive.

它以前被称为 array_view 甚至更早于 array_ref

It was formerly known as an array_view and even earlier as array_ref.

首先,当使用它时:


  • Don'不要在可能需要任何启动和启动对的代码中使用它结束迭代器,例如 std :: sort std :: find_if std :: copy 以及所有这些超通用的模板化函数。

  • 如果您具有标准库容器(或Boost容器等),则不要使用它知道最适合您的代码。

  • Don't use it in code that could just take any pair of start & end iterators, like std::sort, std::find_if, std::copy and all of those super-generic templated functions.
  • Don't use it if you have a standard library container (or a Boost container etc.) which you know is the right fit for your code. It's not intended to supplant any of them.

现在何时实际使用它:


使用 span< T> (分别是 span< const T> ),而不是具有长度值的独立的 T * (分别为 const T * )。因此,替换如下函数:

Use span<T> (respectively, span<const T>) instead of a free-standing T* (respectively const T*) for which you have the length value. So, replace functions like:

  void read_into(int* buffer, size_t buffer_size);

具有:

  void read_into(span<int> buffer);




为什么要使用它?



哦,跨度很棒!使用 span ...


  • 是可以使用的该指针+长度/开始+结束指针的组合,就像您使用的是带有花哨的标准库容器一样,例如:

  • means that you can work with that pointer+length / start+end pointer combination like you would with a fancy, pimped-out standard library container, e.g.:


  • for(auto& x:my_span){/ *做东西* /}

  • std :: find_if(my_span .begin(),my_span.end(),some_predicate);




...但是绝不会产生任何开销,大多数容器类都会产生。

... but with absolutely none of the overhead most container classes incur.

让编译器有时为您做更多的工作。例如:

lets the compiler do more work for you sometimes. For example, this:

int buffer[BUFFER_SIZE];
read_into(buffer, BUFFER_SIZE);

变为:

int buffer[BUFFER_SIZE];
read_into(buffer);

...这将执行您想要的操作。另请参见准则P.5

... which will do what you would want it to do. See also Guideline P.5.

是在您期望将 const vector< T>& 传递给函数时的合理替代方案数据在内存中是连续的。

is the reasonable alternative to passing const vector<T>& to functions when you expect your data to be contiguous in memory. No more getting scolded by high-and-mighty C++ gurus!

使用 span ,您可以在 C ++核心指南中找到-

There's even more motivation for using spans, which you could find in the C++ core guidelines - but you catch the drift.

它在标准库中-但仅从C ++ 20开始。原因是它与 C ++结合使用时,它的当前形式仍然很新。核心指南项目,该项目从2015年才开始形成。(尽管评论者指出,它的历史更早。)

It is in the standard library - but only as of C++20. The reason is that it's still pretty new in its current form, conceived in conjunction with the C++ core guidelines project, which has only been taking shape since 2015. (Although as commenters point out, it has earlier history.)

它是核心准则的支持库(GSL)。实现:

It's part of the Core Guidelines's Support Library (GSL). Implementations:


  • Microsoft / Neil Macintosh的 GSL 包含一个独立的实现: gsl / span

  • GSL-Lite 是整个GSL的单头实现(它并不大,不用担心),包括 span< T>

  • Microsoft / Neil Macintosh's GSL contains a standalone implementation: gsl/span
  • GSL-Lite is a single-header implementation of the whole GSL (it's not that big, don't worry), including span<T>.

GSL实现通常假定平台实现C ++ 14支持[ 14 ]。这些替代的单头实现不依赖于GSL功能:

The GSL implementation does generally assume a platform that implements C++14 support [14]. These alternative single-header implementations do not depend on GSL facilities:

  • martinmoene/span-lite requires C++98 or later
  • tcbrindle/span requires C++11 or later

请注意,这些不同的span实现在它们所使用的方法/支持功能上有所不同。并且它们也可能与标准库C ++ 20中的版本有所不同。

Note that these different span implementations have some differences in what methods/support functions they come with; and they may also differ somewhat from the version going into the standard libraryin C++20.

更多阅读内容::您可以在C ++ 17,P0122R7之前的最终正式建议中找到所有详细信息和设计注意事项: span:对象序列的边界安全视图,作者:尼尔·麦金托夫(Neal Macintosh)和斯蒂芬·拉瓦韦(Stephan J. Lavavej)虽然有点长。另外,在C ++ 20中,跨度比较语义发生了变化(这篇简短论文,作者:托尼·范·埃德(Tony van Eerd)。

Further reading: You can find all the details and design considerations in the final official proposal before C++17, P0122R7: span: bounds-safe views for sequences of objects by Neal Macintosh and Stephan J. Lavavej. It's a bit long though. Also, in C++20, the span comparison semantics changed (following this short paper by Tony van Eerd).

这篇关于什么是“跨度”?我什么时候应该使用一个?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆