STL 入門
STL
STL (standard template library) は,テンプレートクラスやテンプレート関数から構成されるライブラリ。
STL は C++ 標準ライブラリの一部であり,次のようなものが含まれます。
- コンテナ
- イテレータ
- アルゴリズム
- ファンクタ
ここでは,コンテナから vector,アルゴリズムから sort,ファンクタから greater を取り上げて紹介します。
コンテナ
配列のように,複数のオブジェクトを管理するオブジェクトをコンテナ (container) といいます。
STL で提供されている代表的なコンテナに,次のようなものがあります。
- 直列コンテナ: vector, list, deque
- 連想コンテナ: map, set
- コンテナアダプタ: stack, queue
ここでは,最も基本的でよく使われる vector を紹介します。
vector は可変長配列を提供するもので,従来の配列の代わりとしてよく使われます。
次のプログラムは,vector を利用したプログラムの例です。
vector を利用するにはヘッダ vector をインクルードします。
#include <vector>
#include <iostream>
int main()
{
std::vector<int> vec;
vec.push_back(2);
vec.push_back(4);
vec.push_back(6);
vec.push_back(8);
for (int i = 0; i < vec.size(); ++i)
std::cout << vec[i] << std::endl; // 出力: 2, 4, 6, 8
return 0;
}
vector のインスタンス化は,vec(4) のように要素数を指定してもいいです。
ただし,このコンストラクタは全要素の初期化を行うため,結果的に必ずしも効率がよいとは限らありません。
i 番目の要素にアクセスするには,vec[i] と書くか,vec.at(i) と書きます。
不正な添字に対して,前者は無頓着ですが,後者は out_of_range 例外を投げます。
コンテナの要素にアクセスするための,より一般的な方法は,イテレータ (iterator, 反復子) を使う方法です。
#include <vector>
#include <iostream>
int main()
{
std::vector<int> vec;
vec.push_back(2); vec.push_back(4);
vec.push_back(6); vec.push_back(8);
for (std::vector<int>::iterator it = vec.begin();
it != vec.end(); ++it)
std::cout << *it << std::endl; // 出力: 2, 4, 6, 8
return 0;
}
これは,配列を用いた次のプログラムに概ね同等です。
int main()
{
int arr[] = { 2, 4, 6, 8 };
for (int* it = arr; it != arr + 4; ++it)
std::cout << *it << std::endl; // 出力: 2, 4, 6, 8
return 0;
}
std::vector<T>::iterator は,typedef で定義されたイテレータの型です。
first = vec.begin(), last = vec.end() のとき,vec の要素は右半開区間 [first, last) に存在します。
アルゴリズム
コンテナ要素のソートなど,コンテナの操作を行うテンプレート関数を,STL ではアルゴリズム (algorithm) と呼びます。
アルゴリズムを利用するには,ヘッダ algorithm をインクルードします。
次のプログラムは,アルゴリズム sort を利用して,コンテナ要素の並び替えを行う例です。
#include <algorithm>
#include <vector>
#include <iostream>
int main()
{
std::vector<int> vec;
vec.push_back(3); vec.push_back(2); vec.push_back(6);
vec.push_back(4); vec.push_back(1); vec.push_back(5);
std::sort(vec.begin(), vec.end()); // ソート
for (std::vector<int>::iterator it = vec.begin();
it != vec.end(); ++it)
std::cout << *it << std::endl; // 出力: 1, 2, 3, 4, 5, 6
return 0;
}
ファンクタ
関数呼び出し演算子 () をオーバーロードしたクラスを,ファンクタ (functor) または関数オブジェクトと呼ぶことがあります。
STL で提供されているファンクタを利用するには,ヘッダ functional をインクルードします。
アルゴリズム sort の第 3 引数に関数を与えると,それに従ったソートができます。
STL で提供されているファンクタ greater を与えれば,降順によるソートができます。
次のプログラムは,ファンクタ greater を利用して,コンテナ要素を降順にソートするものです。
#include <algorithm>
#include <functional>
#include <vector>
#include <iostream>
int main()
{
std::vector<int> vec;
vec.push_back(3); vec.push_back(2); vec.push_back(6);
vec.push_back(4); vec.push_back(1); vec.push_back(5);
std::sort(vec.begin(), vec.end(), std::greater<int>());
for (std::vector<int>::iterator it = vec.begin();
it != vec.end(); ++it)
std::cout << *it << std::endl; // 出力: 6, 5, 4, 3, 2, 1
return 0;
}
ファンクタを自前で用意するなら,次のようなプログラムが書けます。
#include <algorithm>
#include <vector>
#include <iostream>
// std::greater<int> 相当のファンクタ
class GreaterInt
{
public:
// 演算子 () をオーバーロード
bool operator()(const int& a, const int& b)
{ return a > b; }
};
int main()
{
std::vector<int> vec;
vec.push_back(3); vec.push_back(2); vec.push_back(6);
vec.push_back(4); vec.push_back(1); vec.push_back(5);
std::sort(vec.begin(), vec.end(), GreaterInt());
for (std::vector<int>::iterator it = vec.begin();
it != vec.end(); ++it)
std::cout << *it << std::endl; // 出力: 6, 5, 4, 3, 2, 1
return 0;
}