STLコンテナ
[前のレッスンでは]、[templateについて学びました]――[これにより]関数[や]クラスが[任意の]型に対応できるようになります。
[ただし、実際の]プロジェクト[では]、[自分で]コンテナ([例えば動的]配列や[リンクリスト]など)を[書く必要はありません]。
C++の[標準]テンプレート[ライブラリ](STL)には、[すぐに使える]コンテナが[用意されている]ので、[そのまま使えばいい]!
1. STLとは?
STL(Standard Template Library、[標準]テンプレート[ライブラリ])は、C++の[標準ライブラリの一部]であり、以下を[含んでいます]:
| [構成要素] | [役割] | 例 |
|---|---|---|
| コンテナ | [データ保存] | std::vector、std::array |
| イテレータ | [コンテナの反復処理] | begin()、end() |
| アルゴリズム | [操作データ] | std::sort、std::find |
| functionobject | [カスタム比較ロジック] | std::less、std::greater |
💡 [要点]: STLはテンプレートで[実装されている]ため、[任意の]型をサポートできます。
2. ベクトル([最もよく使われる])
(1) 2.1 ベクトルとは何か?
std::vector [はい][動的]配列——[サイズが自動的に拡大する]。
| [比較] | [通常]配列 | ベクトル |
|---|---|---|
| [サイズ] | [固定] | [動的] |
| メモリ | スタック[または]ヒープ | ヒープ |
| [要素へのアクセス] | arr[i] |
vec[i] [または] vec.at(i) |
| [おすすめ度] | ⭐⭐ | ⭐⭐⭐⭐⭐ |
▶ サンプル 1: vector [基本用法] (難易度 ⭐)
#include iostream
#include vector
int main() {
// int vector
std::vectorint vec = {1, 2, 3, 4, 5};
// ...
std::cout << ":" << vec[0] << std::endl;
std::cout << ":" << vec.at(1) << std::endl;
// ...
vec[0] = 100;
// ...
std::cout << ":" << vec.size() << std::endl;
return 0;
}
💡 [ヒント]: vec.at(i) [は][境界外チェックを行う],[境界外の場合は]例外をスローする;vec[i] [はチェックを行わない],[効率が高い]。
(2) 2.2 [要素の追加と削除]
#include iostream
#include vector
int main() {
std::vectorint vec;
// ...
vec.push_back(10);
vec.push_back(20);
vec.push_back(30);
// ...
vec.pop_back();
// ...
vec.insert(vec.begin() + 1, 15); // 15
// ...
vec.erase(vec.begin() + 1); // ...
return 0;
}
(3) 2.3 [ベクトルの反復処理]
[方法1]:[添字による反復]([最も一般的])
#include iostream
#include vector
int main() {
std::vectorint vec = {1, 2, 3, 4, 5};
for (size_t i = 0; i < vec.size(); i++) {
std::cout << vec[i] << " ";
}
std::cout << std::endl;
return 0;
}
[方法2]:[適用範囲] for(C++11、[推奨])
#include iostream
#include vector
int main() {
std::vectorint vec = {1, 2, 3, 4, 5};
for (int x : vec) {
std::cout << x << " ";
}
std::cout << std::endl;
return 0;
}
[方法3]:イテレータ([後述])
#include iostream
#include vector
int main() {
std::vectorint vec = {1, 2, 3, 4, 5};
for (auto it = vec.begin(); it != vec.end(); ++it) {
std::cout << *it << " ";
}
std::cout << std::endl;
return 0;
}
💡 [おすすめ]: [優先的に使用][範囲] for(C++11)、[最も簡潔]。
3. array([固定サイズ]array)
(1) 3.1 配列とは何か?
std::array [これは][固定サイズ][の]配列であり、[しかし] [通常の]配列よりも[安全]です。
| [比較] | [通常]配列 | 配列 |
|---|---|---|
| [サイズ] | [知っておくべきこと] | [使用方法] size() [入手方法] |
| [退化してしまうか]ポインタ | [はい] | [いいえ] |
| [おすすめ度] | ⭐⭐ | ⭐⭐⭐⭐ |
▶ サンプル 2: array [基本用法] (難易度 ⭐)
#include iostream
#include array
int main() {
// 5 int array
std::array<int, 5> arr = {1, 2, 3, 4, 5};
// ...
std::cout << ":" << arr[0] << std::endl;
// ...
std::cout << ":" << arr.size() << std::endl;
return 0;
}
💡 [要点]: std::array [のサイズは]コンパイル時に[決定][される]もので、[変更することはできない]。
4. deque([両端キュー])
(1) 4.1 dequeとは何か?
std::deque [はい][両端キュー]――[両端]で[要素を]素早く[追加]・[削除]できる。
| [操作] | vector | deque |
|---|---|---|
| [末尾追加] | O(1) | O(1) |
| [先頭に追加] | O(n) | O(1) |
| [ランダムアクセス] | O(1) | O(1) |
▶ サンプル 3: deque [基本用法] (難易度 ⭐⭐)
#include iostream
#include deque
int main() {
std::dequeint dq;
// ...
dq.push_back(10);
dq.push_back(20);
// ...
dq.push_front(5);
dq.push_front(1);
// dq:1, 5, 10, 20
for (int x : dq) {
std::cout << x << " ";
}
std::cout << std::endl;
return 0;
}
5. リスト([双方向連結リスト])
(1) 5.1 「リスト」とは何か?
std::list [はい][双方向連結リスト]——[各要素には、前後の要素の]アドレスが格納されている。
| [比較] | ベクトル | リスト |
|---|---|---|
| [ランダムアクセス] | O(1) | ❌ [非対応] |
| [挿入]/[削除] | O(n) | O(1) |
| メモリ[使用量] | [小] | [大]([各要素につき2つのポインタを追加]) |
▶ サンプル 4: list [基本用法] (難易度 ⭐⭐)
#include iostream
#include list
int main() {
std::listint lst = {1, 2, 3, 4, 5};
// ...
lst.push_front(0);
// ...
lst.push_back(6);
// 3
lst.remove(3);
for (int x : lst) {
std::cout << x << " ";
}
std::cout << std::endl;
return 0;
}
6. forward_list([単方向連結リスト])
(1) 6.1 forward_list とは何か?
std::forward_list [はい][単方向連結リスト]——[各要素には、1つの要素の]アドレスだけが格納される。
| [比較] | リスト | フォワードリスト |
|---|---|---|
| メモリ[使用量] | [大きい] | [小さい] |
| [前方へ走査できますか]? | ✅ | ❌ |
| [おすすめ度] | ⭐⭐⭐⭐ | ⭐⭐([特定の場面向け]) |
💡 [アドバイス]: [確実に]**[後方のみを走査すればよい]と[確信している場合]を除き、[そうでない場合は] std::listを使用してください。
7. コンテナ【選び方のガイド】
| [シーン] | [おすすめ]コンテナ |
|---|---|
| [動的なサイズが必要] | std::vector |
| [サイズ固定]、[保持] C [スタイル] | std::array |
| [ヘッダーに素早く追加]/[削除] | std::deque |
| [頻繁に中間への挿入]/[削除]が必要 | std::list |
| [後ろに向かって走査するだけでよい]、[かつメモリを節約する] | std::forward_list |
💡 [黄金律]: [優先して] std::vector を使用し、[[明確な理由]がある場合を除き]、[他のもの]を使用する。
8. 演習:[vector を使用して] 動的配列を実装する (難易度 ⭐⭐)
#include iostream
#include vector
#include string
struct Student {
std::string name;
int age;
double score;
};
int main() {
std::vectorStudent students;
// ...
students.push_back({"Alice", 20, 92.5});
students.push_back({"Bob", 21, 88.0});
students.push_back({"Charlie", 19, 95.0});
// output
for (const auto& s : students) {
std::cout << ":" << s.name
<< ",:" << s.age
<< ",:" << s.score << std::endl;
}
return 0;
}
❓ よくある質問
Q:vector [と] array [の違いは何ですか]? A:> -
vector[サイズ][動的]、[ヒープ]上に存在する > -array[サイズ][固定]、[スタック]上に存在する > > [選択のアドバイス]: [サイズが不確定な場合]、vectorを使用;[サイズが固定でかつ小さい場合]、array[を使用]。 Q:[なぜ] vector [の反復処理には] for [範囲指定] が推奨されるのですか? A:[より簡潔] であり、[ループ条件] を[書き間違えにくい] からです。 > > // [従来の] for([書き間違えやすい]条件) > for (size_t i = 0; i < vec.size(); i++) { ... } > > // [範囲] for([簡潔]、[ミスが少ない]) > for (int x : vec) { ... } > Q:list [と] vector [どちらが速い]? A:[状況による]: > - [もし][ランダムアクセス]が必要なら(vec[100])、vector[速い] > - [中間への挿入]/[削除]が必要な場合、list[速い]
Q:STL containersについて最も重要なことは何ですか? A:まず核心概念を理解し、その後実践的な例で練習することが重要です。
📖 まとめ
- STLコンテナ[は] C++ [の標準ライブラリが提供する既製のデータ構造]
- ベクトル [最もよく使われる]([動的]配列)
- 配列 [固定サイズのシーン用]
- deque [両端からの高速操作に対応]
- リスト [双方向連結リスト],[頻繁な挿入]/[削除]に適している
- [優先的に] vectorを使用すること。[他に明確な理由がある場合を除き]
📝 練習問題
-
初心者(難易度 ⭐): [入力]
std::vectorint[保存] 5 [個の整数],[それらを順に処理して]出力する。 -
中級(難易度 ⭐⭐): [用]
std::vectorstd::string[3つの]文字列を保存し、[ユーザーに]入力させ、[その後]出力する。 -
上級(難易度 ⭐⭐⭐): [用]
std::deque[実現]「回文 [検出]」:
-
[両端から中央に向かって比較し]、[対応する文字がすべて等しければ]、[それは] 回文である
-
例:
"racecar"[は] 回文、"hello"[ではない] -
STLコンテナ[分]クラス:[シーケンシャル型](vector/list/deque)[集合・関連型](set/map)
-
ベクトル [動的]配列:[末尾の追加・削除が高速]、[ランダムアクセスに対応]
-
リスト [双方向連結リスト]:[任意の位置への挿入が高速]
-
map [キー]値[ペア]コンテナ:[キー順]、[検索] O(log n)
-
set [集合] コンテナ:[要素一意]、[自動ソート]
9. 🚀 次は
[STLコンテナ[の基礎]を学びました]。[次は] STLアルゴリズム([第]35[回])を学びます―― [標準ライブラリが提供する]algorithmを使って[コンテナを操作]し、[自分でソートや検索のコードを書く必要はありません]……



