1. 導入:なぜstd::listが必要なのか?
C++の標準ライブラリ(STL)には、データを保持する「コンテナ」がたくさん用意されています。よく使われるのは std::vector ですが、実は「途中の要素を頻繁に削除・追加する」処理には向いていません。そこで登場するのが std::list です。std::listを使うことで、データの挿入や削除というコストの高い処理を、場所に関わらず瞬時に終わらせることができるようになります。
2. 基礎知識:連結リスト(Linked List)とは?
std::listは「双方向リンクリスト」という仕組みでできています。これは、各データが前後のデータの「場所(アドレス)」を指し示すメモを持っている構造です。
・std::vector:本棚のようにデータが隙間なく並んでいる。途中に本を入れるには、後ろの本をすべてずらす必要がある。
・std::list:数珠つなぎのようにデータがつながっている。途中の紐をほどいて新しいデータを繋ぐだけでいいので、ずらす必要がない。
この仕組みのおかげで、リストのどこであっても、要素の追加・削除が一定の時間(計算量 O(1))で完了します。
3. 実装/解決策:std::listを使いこなす
std::listを扱うには、ヘッダーファイル をインクルードします。要素の追加には push_back(末尾)や push_front(先頭)を使い、途中に挿入したい場合は「イテレータ(指し示す位置)」を指定して insert を使います。
4. サンプルプログラム
以下のコードをコピーして、実際に動かしてみてください。
include <iostream>
include <list>
int main() {
// リストの初期化
std::list<int> numbers = {10, 20, 30};
// 末尾に追加
numbers.push_back(40);
// 先頭に追加
numbers.push_front(5);
// リストの途中に要素を挿入する
// begin()は先頭を指すイテレータ。+1して2番目の位置へ移動
auto it = numbers.begin();
std::advance(it, 1);
numbers.insert(it, 15); // 5と10の間に15を挿入
// 範囲ベースforループで表示
for (int n : numbers) {
std::cout << n << " ";
}
std::cout << std::endl;
return 0;
}
5. 応用・注意点:使い分けが重要!
std::listは強力ですが、万能ではありません。注意すべきポイントは以下の2点です。
1. ランダムアクセスができない:
std::vectorのように「3番目のデータ」をすぐに見ることはできません。リストの先頭から順番に辿る必要があるため、要素の検索には時間がかかります。
2. メモリ効率:
各データに対して「前後の場所を指すポインタ」という管理用のメモリが必要なため、std::vectorよりもメモリ使用量が多くなりがちです。
結論:
・順番にアクセスする、あるいは途中の追加・削除が多いなら std::list
・特定の番号へのアクセスが多い、あるいはメモリを節約したいなら std::vector
というように、用途に合わせて選ぶのがC++エンジニアの第一歩です!

コメント