1. 導入:なぜstd::forward_listが必要なのか
C++でデータをリスト形式で管理したいとき、多くの方が std::vector や std::list を思い浮かべるでしょう。しかし、要素がそれほど多くない場合や、メモリ使用量を極限まで抑えたいという場面では、これらは「少し贅沢」かもしれません。
そこで登場するのが std::forward_list です。これは「単方向リンクリスト」と呼ばれるデータ構造で、メモリ効率を最優先した設計になっています。この記事では、std::forward_listの仕組みと、賢い使い方を解説します。
2. 基礎知識:単方向リンクリストとは?
一般的な std::list(双方向リンクリスト)は、各要素が「前の要素」と「次の要素」の両方へのポインタを持っています。これにより双方向の移動が可能ですが、その分ポインタが2つ必要となり、メモリを消費します。
一方、std::forward_list は「次の要素」へのポインタしか持ちません。これが「単方向」という名前の由来です。
・メリット:メモリ消費量が極めて小さい。
・デメリット:逆方向に辿ることはできない。また、末尾へのアクセスや追加は苦手。
この「割り切り」こそが、std::forward_list の最大の強みです。
3. 実装/解決策:基本的な操作手順
std::forward_list は、「先頭」に対する操作が非常に高速です。要素の追加・削除は、先頭(push_front)に行うのが基本ルールです。途中に要素を挿入したい場合は、イテレータを使って直前の要素を指定して行います。
4. サンプルプログラム
以下のコードは、std::forward_list の基本的な作成、要素の追加、全要素の走査を行う例です。そのままコピーしてコンパイルしてみてください。
include
include
int main() {
// リストの初期化
std::forward_list
// 先頭に要素を追加 (push_frontのみ利用可能)
fl.push_front(5);
// 全要素を表示
std::cout << "リストの内容: ";
for (int n : fl) {
std::cout << n << " ";
}
std::cout << std::endl;
// 2番目の要素を削除する例
// begin()の次の要素を削除するには erase_after を使用します
auto it = fl.begin();
fl.erase_after(it);
std::cout << "削除後の内容: ";
for (int n : fl) {
std::cout << n << " ";
}
std::cout << std::endl;
return 0;
}
5. 応用・注意点:現場での使いどころ
std::forward_list を使う際に最も注意すべき点は、「サイズ(size())を取得できない」ことです。現在の要素数がいくつあるかを知るには、自分で最初から最後までループを回してカウントする必要があります。もし頻繁にサイズを確認する必要があるなら、std::vector を検討してください。
また、挿入や削除を行う際は insert_after や erase_after といった「~の後ろ」というメソッドを使うのが特徴です。これは、「前の要素」の情報を持たない単方向リスト特有の仕様ですので、覚えておくと現場で迷わずに済みます。メモリ制限が厳しい組み込み環境や、大量の小規模リストを扱う場合には非常に強力な武器になります。

コメント