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;
}
スポンサーリンク