[解決済み】「span」とは何ですか、どんな時に使うのですか?
質問
最近
span<T>
を使用している回答も見受けられます。
span
は、ある種のコンテナと思われます。しかし、C++17の標準ライブラリには、そのようなものは見当たりません。
では、この謎の
span<T>
そして、なぜ(あるいはいつ)、非標準のものを使うのがよいのでしょうか?
どのように解決するのですか?
何ですか?
A
span<T>
があります。
-
型の連続した値の非常に軽量な抽象化である。
T
メモリ上のどこかにある。 -
基本的には
struct { T * ptr; std::size_t length; }
という便利なメソッドをたくさん持っています。 - 非所有型(すなわち "参照型" 値型ではなく)。割り当てや解放を行わず、スマートポインターを生かさない。
以前は
array_view
として、さらに以前は
array_ref
.
どのような場合に使用すればよいですか?
まず、次のような場合です。 ない を使用することです。
-
のような、開始と終了のイテレータのペアを取るようなコードでは使用しないでください。
std::sort
,std::find_if
,std::copy
といった超一般的なテンプレート化された関数のすべてです。 - 標準ライブラリコンテナ(またはBoostコンテナなど)があり、それがあなたのコードに適していることがわかっている場合は、使用しないでください。これは、それらに取って代わることを意図したものではありません。
では、実際に使用する場合についてです。
使用方法
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.cbegin(), my_span.cend(), some_predicate);
-
std::ranges::find_if(my_span, some_predicate);
(C++20の場合)
... しかし、ほとんどのコンテナクラスで発生するオーバーヘッドが全くありません。
-
-
は、時にはコンパイラにもっと仕事をさせることができます。例えば、こんな感じです。
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
) -
は、(span を使用している) あなたのコードが、指されたメモリを所有していないことを示します。
を使用する動機はさらにあります。
span
の中に見つけることができます。
C++コアガイドライン
- ということなのですが、流れはつかめますよね。
でも、標準ライブラリにあるのですか?
を編集してください。
はい。
std::span
は、C++のC++20バージョンで追加されました
なぜC++20だけなのか?このアイデアは新しいものではありませんが、現在の形はC++20と一緒に考え出されたものです。 C++コア・ガイドライン プロジェクトが具体化し始めたのは2015年です。だから時間がかかったんですね。
では、C++17以前の言語を書いている場合、どのように使えばいいのでしょうか?
の一部です。 コア・ガイドライン のサポートライブラリ(GSL)です。実装しています。
-
マイクロソフト / ニール・マッキントッシュの
GSL
には、スタンドアロンの実装が含まれています。
gsl/span
-
GSL-Lite(ライト
は、GSL 全体のシングルヘッダー実装です (そんなに大きくないので、心配しないでください)。
span<T>
.
GSL の実装は一般的に C++14 をサポートするプラットフォームを想定しています [... 11 ]. これらの代替のシングルヘッダー実装はGSL機能に依存しません。
-
martinmoene/span-lite
C++98以降が必要 -
tcbrindle/span
C++11以降が必要
なお、これらの異なるspanの実装は、搭載しているメソッドやサポート関数に違いがあり、C++20で標準ライブラリに採用されたバージョンとは多少異なる場合があります。
さらに読む C++17 前の最終的な公式提案である P0122R7 に、すべての詳細と設計上の考慮事項が記載されています。 span: オブジェクトのシーケンスに対する境界安全性の高いビュー Neal Macintosh と Stephan J. Lavavej によるものです。ちょっと長いですけど。また、C++20では、スパン比較のセマンティクスが変更された(以下のように この短い論文 Tony van Eerdによる) 。
関連
-
[解決済み】C++エラー。アーキテクチャ x86_64 に対して未定義のシンボル
-
[解決済み】LLVMで暗黙のうちに削除されたコピーコンストラクタの呼び出し
-
[解決済み】Visual C++で "Debug Assertion failed "の原因となる行を見つける。
-
[解決済み】システムが指定されたファイルを見つけられませんでした。
-
[解決済み] static_cast, dynamic_cast, const_cast, reinterpret_cast はいつ使うべきですか?
-
[解決済み] コピーアンドスワップ慣用句とは?
-
[解決済み] スマートポインターとは何ですか?
-
[解決済み] なぜ、オブジェクトそのものではなく、ポインタを使用しなければならないのですか?
-
[解決済み] const int*、const int * const、int const *の違いは何ですか?
-
[解決済み] C++の識別子でアンダースコアを使用する場合のルールについて教えてください。
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】 unsigned int vs. size_t
-
[解決済み】C++ 非推奨の文字列定数から「char*」への変換について
-
[解決済み】C++のGetlineの問題(オーバーロードされた関数 "getline "のインスタンスがない
-
[解決済み】C++ 式はポインタからオブジェクトへの型を持っている必要があります。
-
[解決済み】C++プログラムでのコンソールの一時停止
-
[解決済み】システムが指定されたファイルを見つけられませんでした。
-
[解決済み】ベクトルからサブベクトルを抽出する最適な方法とは?
-
[解決済み] 配列からポインタへの減衰とは何ですか?
-
[解決済み] リファレンスとポインタの使い分け
-
[解決済み】なぜC++にはガベージコレクタがないのですか?