STLコンテナ
vector, list, map, set など.
vector(動的配列)
最も使用頻度の高いコンテナ。メモリは連続しており、ランダムアクセスが高速です。
#include <iostream>
#include <vector>
int main() {
std::vector<int> v = {1, 2, 3, 4, 5};
v.push_back(6);
v.pop_back(); // 最後の要素を削除
std::cout << "サイズ: " << v.size() << std::endl;
std::cout << "容量: " << v.capacity() << std::endl;
for (int x : v) std::cout << x << " ";
std::cout << std::endl;
return 0;
}
サイズ: 5
容量: 8
1 2 3 4 5
vectorのメモリ管理
reserve() で事前にメモリ確保。shrink_to_fit() で余分な容量を削減します。
#include <iostream>
#include <vector>
int main() {
std::vector<int> v;
v.reserve(100); // 事前に100個分のメモリ確保
// 100個の要素を追加
for (int i = 0; i < 100; ++i) {
v.push_back(i);
}
std::cout << "サイズ: " << v.size()
<< ", 容量: " << v.capacity() << std::endl;
// 容量を削減
v.resize(50); // 要素数を50に
v.shrink_to_fit(); // 余分な容量を削除
std::cout << "縮小後: サイズ: " << v.size()
<< ", 容量: " << v.capacity() << std::endl;
return 0;
}
サイズ: 100, 容量: 100
縮小後: サイズ: 50, 容量: 50
deque(両端キュー)
vectorと似ていますが、前後両端への挿入・削除が効率的です。
#include <iostream>
#include <deque>
int main() {
std::deque<int> dq = {2, 3, 4};
dq.push_front(1); // 前に要素追加
dq.push_back(5); // 後に要素追加
dq.pop_front(); // 前から削除
for (int x : dq) std::cout << x << " ";
std::cout << std::endl;
return 0;
}
2 3 4 5
list(リスト)
双方向リンクリスト。中間への挿入・削除が効率的。ランダムアクセスはできません。
#include <iostream>
#include <list>
int main() {
std::list<std::string> colors = {"red", "blue"};
auto it = colors.begin();
++it;
colors.insert(it, "green"); // イテレータの位置に挿入
for (const auto& c : colors) {
std::cout << c << " ";
}
std::cout << std::endl;
return 0;
}
red green blue
map(連想配列)
キー-値ペアを保持。キーでソートされています。O(log N)の検索。
#include <iostream>
#include <map>
#include <string>
int main() {
std::map<std::string, int> ages;
ages["太郎"] = 25;
ages["花子"] = 23;
ages["次郎"] = 28;
// 自動的にキーでソート
for (const auto& [name, age] : ages) {
std::cout << name << ": " << age << std::endl;
}
// 存在確認
if (ages.count("太郎") > 0) {
std::cout << "太郎が見つかりました" << std::endl;
}
return 0;
}
太郎: 25
花子: 23
次郎: 28
太郎が見つかりました
set(セット)
重複なしのソート済み集合。mapと同様にO(log N)。
#include <iostream>
#include <set>
#include <vector>
int main() {
std::vector<int> data = {5, 2, 8, 2, 1, 8, 3};
std::set<int> unique(data.begin(), data.end()); // 重複を削除
std::cout << "重複削除後: ";
for (int x : unique) std::cout << x << " ";
std::cout << std::endl;
// 挿入と検索
unique.insert(7);
if (unique.find(7) != unique.end()) {
std::cout << "7が見つかりました" << std::endl;
}
return 0;
}
重複削除後: 1 2 3 5 8
7が見つかりました
unordered_map と unordered_set
ハッシュテーブルベースのコンテナ。ソートされておらず、平均的に O(1) の高速検索。
#include <iostream>
#include <unordered_map>
#include <unordered_set>
int main() {
// unordered_map: 順序なし、高速検索
std::unordered_map<std::string, int> scores;
scores["Alice"] = 85;
scores["Bob"] = 92;
scores["Charlie"] = 78;
std::cout << "Alice: " << scores["Alice"] << std::endl;
// unordered_set: 順序なし、ユニーク要素
std::unordered_set<int> ids = {101, 202, 303, 202}; // 202は1回だけ
std::cout << "ユニークなID数: " << ids.size() << std::endl;
return 0;
}
Alice: 85
ユニークなID数: 3
よくある誤り
- 誤り:
v[i]で範囲外アクセス → 改善:v.at(i)で例外ポーション - 誤り:
map["key"]で存在しないキー → 改善:map.find("key") != map.end()で確認 - 誤り: listに
[]でアクセス → 改善: イテレータまたはループで走査 - 誤り: capacity と size の混同 → vector の容量は size() より大きい場合がある
ポイント
- vector: 高速ランダムアクセス、背後のメモリは連続
- deque: 両端への高速插入・削除
- list: 中間への高速插入・削除、しかしランダムアクセスは遅い
- map/set: ソート済み、O(log N)検索
- unordered_map/set: ハッシュベース、平均 O(1) 検索
- reserve() で事前にメモリ確保して性能向上