関数へのspanの渡し方
柔軟なAPIを記述します
「関数へのspanの渡し方」はCoddyKit上の無料C++ Academyレッスンです。 これはレッスン3/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはC++ Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 C++ Academyコースには全4レッスンが含まれています。
1つの関数で多くのコンテナーに対応
std::spanを受け取る関数は、配列、vector、生のバッファーを同じように受け取れます。テンプレートやオーバーロードは必要ありません。
#include <iostream>
#include <span>
#include <vector>
#include <array>
int sum(std::span<const int> s) {
int t = 0; for (int x : s) t += x; return t;
}
int main() {
std::vector<int> v = {1, 2, 3};
std::array<int, 2> a = {4, 5};
std::cout << sum(v) << " " << sum(a) << "\n";
}サイズ引数が不要
従来のC形式APIでは、ポインターとサイズを別々に渡します。spanはこの2つをまとめるため、長さの不一致によるバグを防げます。
#include <iostream>
#include <span>
void printAll(std::span<const int> s) {
for (int x : s) std::cout << x << " ";
std::cout << "\n";
}
int main() {
int buf[] = {7, 8, 9};
printAll(buf); // size inferred
}読み取り専用にはconst span
std::span<const T>を使用すると、関数が呼び出し元のデータを変更しないことを保証できます。
#include <iostream>
#include <span>
int maxOf(std::span<const int> s) {
int m = s[0];
for (int x : s) if (x > m) m = x;
return m;
}
int main() {
int data[] = {3, 9, 4};
std::cout << maxOf(data) << "\n"; // 9
}編集には変更可能なspan
constではないspanを使うと、関数から呼び出し元の要素を直接変更できます。
#include <iostream>
#include <span>
#include <vector>
void doubleAll(std::span<int> s) {
for (int& x : s) x *= 2;
}
int main() {
std::vector<int> v = {1, 2, 3};
doubleAll(v);
std::cout << v[2] << "\n"; // 6
}テンプレートの肥大化を回避
spanがなければ、コンテナー型をテンプレート引数にすることになり、多数のインスタンスが生成される可能性があります。spanなら、どのコンテナーにもそのまま使える1つの具体的なシグネチャで済みます。
コピーを回避
spanを渡しても要素はコピーされず、関数に渡されるのはポインターと長さだけです。
#include <iostream>
#include <span>
#include <vector>
size_t count(std::span<const int> s) { return s.size(); }
int main() {
std::vector<int> big(1000, 0);
std::cout << count(big) << "\n"; // no copy of 1000 ints
}空のspanも問題なし
関数は空のspanを適切に処理できるようにしてください。size()は0になり、範囲ベースのループは0回だけ実行されます。
#include <iostream>
#include <span>
int sum(std::span<const int> s) { int t = 0; for (int x : s) t += x; return t; }
int main() {
std::span<const int> empty;
std::cout << sum(empty) << "\n"; // 0
}値渡し
spanは非常に小さいため、参照ではなく値渡ししてください。ポインターと長さのコピーは実質的にコストがかかりません。
constの意図を明示
span<const T>とspan<T>のどちらを選ぶかによって、データを変更できるかどうかを呼び出し元に一目で伝えられます。
所有権は呼び出し元に残る
コンテナーの所有権は呼び出し元に残ります。spanは呼び出し中だけコンテナーを借用します。関数は呼び出しが終わった後までspanを保持してはいけません。
現代的なAPIのスタイル
spanを受け取ることは、連続したデータを扱う関数を記述する現代的で慣用的な方法です。柔軟で安全、かつコピーも発生しません。
理解度チェック
spanの関数への渡し方についての理解度を確認してください。
まとめ
spanを関数に渡す方法について学びました。
- 1つのシグネチャで、配列、vector、バッファーを受け取れます。
- 読み取り専用には
span<const T>を、直接編集する場合はspan<T>を使用します。 - 値渡ししてもコピーは発生しません。
- 所有権は呼び出し元に残るため、呼び出し後までspanを保持してはいけません。
よくある質問
「関数へのspanの渡し方」レッスンは無料ですか?
はい。「関数へのspanの渡し方」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、C++ Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 C++ Academyコースには全4レッスンが含まれています。
「関数へのspanの渡し方」で何を学びますか?
柔軟なAPIを記述します ブラウザで直接実行するハンズオンコードでC++ Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
C++ Academyを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのC++ Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン3/4です。
「関数へのspanの渡し方」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このC++ Academyレッスンでコードを書いて実行できますか?
はい。すべてのC++ Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- 固定長std::array
- std::spanの基礎
- 関数へのspanの渡し方
- 範囲とサブスパン