最近span<T>、コードでを使用するよう提案するか、サイトでを使用するいくつかの回答を見ましたspan。ある種のコンテナだと思われます。しかし、私はC ++ 17標準ライブラリでそのようなものを見つけることができません。
では、この不可解なspan<T>とは何か、そしてそれが非標準である場合、なぜ(またはいつ)使用するのが良いのでしょうか?
gsl::spanではなくstd::span。以下の私の回答も参照してください。
最近span<T>、コードでを使用するよう提案するか、サイトでを使用するいくつかの回答を見ましたspan。ある種のコンテナだと思われます。しかし、私はC ++ 17標準ライブラリでそのようなものを見つけることができません。
では、この不可解なspan<T>とは何か、そしてそれが非標準である場合、なぜ(またはいつ)使用するのが良いのでしょうか?
gsl::spanではなくstd::span。以下の私の回答も参照してください。
回答:
A span<T>は:
Tメモリ内のどこかにある型の値の連続したシーケンスの非常に軽量な抽象化。struct { T * ptr; std::size_t length; }、便利なメソッドがたくさんあります。以前は、以前はとして知られ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...
これは、空想的なピンプアウトされた標準ライブラリコンテナの場合と同様に、そのポインタ+長さ/開始+終了ポインタの組み合わせで作業できることを意味します。例:
for (auto& x : my_span) { /* do stuff */ }std::find_if(my_span.begin(), my_span.end(), some_predicate);
...しかし、ほとんどのコンテナクラスで発生するオーバーヘッドはまったくありません。
コンパイラーがより多くの作業を実行できるようにします。たとえば、これ:
int buffer[BUFFER_SIZE];
read_into(buffer, BUFFER_SIZE);
これになる:
int buffer[BUFFER_SIZE];
read_into(buffer);
...あなたがやりたいことをするでしょう。ガイドラインP.5も参照してください。
const vector<T>&メモリ内でデータが連続していると予想される場合に、関数に渡すのに適した方法です。強力なC ++の教祖たちに叱られることはもうありません!
spanのメソッドには#ifndef NDEBUG... 内にいくつかの境界チェックコードがあります#endif)spans を使用する動機はさらにあります。これはC ++コアガイドラインで見つけることができますが、ドリフトをキャッチします。
これは標準ライブラリにありますが、C ++ 20以降のみです。その理由は、C ++コアガイドラインプロジェクトとの関連で考案された現在の形式では、まだかなり新しいからです。これは、2015年以来、形になっているだけです(コメンターが指摘するように、これには以前の履歴があります)。
これは、コアガイドラインのサポートライブラリ(GSL)の一部です。実装:
gsl/spanspan<T>。GSLの実装では、通常、C ++ 14サポートを実装するプラットフォームを想定しています[ 14 ]。これらの代替シングルヘッダー実装は、GSL機能に依存しません。
martinmoene/span-lite C ++ 98以降が必要tcbrindle/span C ++ 11以降が必要これらの異なるスパンの実装では、付属するメソッド/サポート関数にいくつかの違いがあることに注意してください。また、C ++ 20の標準ライブラリに入るバージョンとは多少異なる場合があります。
深い読み:あなたがC ++ 17の前に、最終的な公式提案ですべての詳細および設計上の考慮事項を見つけることができ、P0122R7:スパン:オブジェクトのシーケンスの境界に安全な景色ニールMacintoshとステファンJ. Lavavejによります。少し長いですが。また、C ++ 20では、スパン比較セマンティクスが変更されました(Tony van Eerdによるこの短い論文に続いて)。
std::cout << sizeof(buffer) << '\n'と、100のsizeof(int)が得られることがわかります。
std::arrayはコンテナであり、値を所有しています。spanは所有されてい
std::array完全に別の獣です。その長さはコンパイル時に固定され、Calethが説明したように、参照型ではなく値型です。
@einpoklumは、ここで彼の回答に a spanが何であるかを紹介するのにかなり良い仕事をしています。ただし、彼の回答を読んだ後でも、スパンに不慣れな人が、次のように、完全には回答されていない一連の思考の質問をまだ持っていることは簡単です。
spanC配列とどう違うのですか?それらの1つだけを使用しないのはなぜですか?サイズもわかっているものの1つにすぎないようです...std::arrayますが、それとどうspan違うのですか?std::vectorようにstd::array、あまりにも?spanですか?それで、それについていくつかの追加の明快さがあります:
彼の答えの直接の引用- 私の追加が太字になっています:
それは何ですか?
A
span<T>は:
Tメモリ内のどこかにある型の値の連続したシーケンスの非常に軽量な抽象化。- 基本的に、便利なメソッドの束を持つ単一の構造体
{ T * ptr; std::size_t length; }。(注意これは明らかに異なっているstd::array<>ためspanに匹敵する方法、アクセッサ利便性を可能にstd::array介して、型へのポインタTタイプおよび長さ(要素の数)Tに対し、std::array一つ以上の保持実際のコンテナである値型は、T。)- 非所有型(つまり、「値型」ではなく「参照型」):何も割り当てたり割り当て解除したりすることはなく、スマートポインターを存続させません。
以前は、以前はとして知られ
array_viewていましたarray_ref。
これらの太字の部分は理解するために重要ですので、見落としたり、読み違えたりしないでください。A spanは構造体のC配列ではなく、タイプのC配列に配列のT長さを加えた構造体でもありません(これは基本的にstd::array コンテナーと同じです)、NORはポインターの構造体のC配列です入力するTプラス長さではなく、それは、単一の単一含む構造体のタイプへのポインタをT、そして長さであり、(タイプの要素数Tポインタを入力することを連続したメモリブロック内)Tにポイントを!このように、使用して追加した唯一のオーバーヘッドは、spanは、ポインタと長さを格納する変数、およびがspan提供する使用する便利なアクセサ関数です。
これはUNLIKE a std::array<>です。これはstd::array<>、が隣接するブロック全体に実際にメモリを割り当てるstd::vector<>ためです。また、std::vector基本的にはa std::arrayがいっぱいになるたびに動的に増加する(通常はサイズが2倍になる)だけなので、UNLIKEになります。 。A std::arrayはサイズが固定されており、a spanはポイントするブロックのメモリを管理することもせず、メモリブロックをポイントするだけで、メモリブロックの長さを知り、C配列内のデータ型を知っています。メモリ内にあり、その連続したメモリ内の要素を操作するための便利なアクセサ関数を提供します。
std::spanC ++ 20以降のC ++標準の一部です。そのドキュメントはhttps://en.cppreference.com/w/cpp/container/spanで読むことができます。今日のabsl::Span<T>(array, length) C ++ 11以降でのGoogleの使用方法については、以下を参照してください。
std::span<T, Extent>(Extent= "シーケンス内の要素の数、またはstd::dynamic_extent動的の場合。"スパンはメモリを指すだけでアクセスを容易にしますが、管理はしません!):
std::array<T, N>(サイズが固定されていることに注意してNください!):
std::vector<T> (必要に応じて自動的に動的にサイズが大きくなります):
span、C ++ 11以降でどのように使用できますか?グーグルは、自社の「Abseil」ライブラリの形で内部C ++ 11ライブラリをオープンソース化しています。このライブラリは、C ++ 14からC ++ 20以降の機能をC ++ 11以降で機能するように提供することを目的としているため、今日の明日の機能を使用できます。彼らが言うには:
C ++標準との互換性
Googleは、C ++ 14、C ++ 17、およびそれ以降に組み込まれている機能に一致またはほぼ一致する多くの抽象化を開発しました。これらの抽象化のAbseilバージョンを使用すると、コードがポストC ++ 11の世界でまだ準備ができていない場合でも、これらの機能に今すぐアクセスできます。
主なリソースとリンクは次のとおりです。
span.hヘッダー、およびabsl::Span<T>(array, length)テンプレートクラス:https : //github.com/abseil/abseil-cpp/blob/master/absl/types/span.h#L189
std::span2017年に提案されました。C++ 17またはC ++ 20に適用されます。P0122R5、スパン:オブジェクトのシーケンスの境界セーフビューも参照してください。その言語をターゲットに設定しますか?コンパイラが追いつくまでには何年もかかるでしょう。