jtwp470’s blog

日記とかプヨグヤミングとか

C++ プログラミング入門 STLを使いこなす

C言語をやってきて早3年位経ちましたがいい加減C++を舐めようかと思い立ちました. C++といえばC++11やC++14など規格がたくさんありますしBoostなどたくさんのライブラリがありますがとりあえずC言語からC++へステップアップする身としてSTL(Standard Template Library)をマスターしておきたいと思います.

STLC言語にはないライブラリで

です.

ま,この項目はいわゆる私的メモみたいなものです.

コンテナ

C++にはさまざまなコンテナが用意されておりそれぞれ違うアルゴリズムによって実装されているため用途に合わせて使いこなす必要があります.

これらの違いや計算量に関してはQiita [C++] STLの型の使い分けというページが非常に詳しく載っています.

使い方 ~ vectorを例にとって ~

よく使うであろうvectorを例にとって調べたことをまとめます.

include

まずvectorを使うためにはヘッダで#include<vector>をする必要があります.

生成

使うためには宣言をします.

std::vector<int> v;

これでint型を格納できるvectorが作られます.

要素を追加する

要素を追加するためにはpush_backメンバ関数を用います.

v.push_back(4); // 4 を新たに追加

なおpush_backはC++編【標準ライブラリ】第5章 vectorに書いてあるとおり

  1. 新しい容量分のメモリを新たに確保する
  2. 以前のデータを新たなメモリ領域へコピーする
  3. 以前のデータがあったメモリ領域を解放する

という処理が行われるため,時間がかかります.つまり以下のような実装は効率が悪いと言えます.

#include <iostream>
#include <vector>

int main() {
    std::vector<int> v;
    for (int i = 0; i < 100000; i++) 
        v.push_back(i);
   return 0;
}

なのでもともとこのくらい使うであろうということがわかっていれば事前にまとまった領域を確保しておいたほうが無難です.

これを行うには次のようにします.

std::vector<int> v(10000);  // 10000個分の確保
v.reserve(20000);             // 20000個分

コンストラクタで初期化したり,reserveメンバ関数を用いて容量を確保しておきます.

要素へのアクセス

vectorはoperatorが定義されているため,通常の配列のようにを使った添字アクセスができます.

添字に0未満や確保している大きさ以上の数を指定した場合,範囲外アクセスとなり何を参照しているのかわかりませんし,非常に危険です.そこで範囲外アクセスを検知したら例外を投げる方法としてat()メンバ関数を用います.するともし範囲外アクセスをしたらstd::out_of_range例外を送出します.

イテレータ

vectorの場合先頭要素を指すのはbeginメンバ関数,末尾要素はendメンバ関数を用います.逆イテレータの場合は最初の要素がrbeginで最後の要素がrendです.

#include <iostream>
#include <vector>

#define MAX 10

int main(void) {
  std::vector<int> v(MAX);

  for (int i = 0; i < MAX; i++)
    v.at(i) = i;

  // 通常
  std::cout << "General iterator" << std::endl;
  for (std::vector<int>::iterator it = v.begin(); it != v.end(); it++)
    std::cout << *it << " ";
  std::cout << std::endl;

  std::cout << "Reverse iterator" << std::endl;
  // 逆方向
  for (std::vector<int>::reverse_iterator it = v.rbegin(); it != v.rend(); it++)
    std::cout << *it << " ";
  std::cout << std::endl;
  return 0;
}

実行例:

General iterator
0 1 2 3 4 5 6 7 8 9 
Reverse iterator
9 8 7 6 5 4 3 2 1 0 

ちなみにC++11ではautoという型推論予約語が追加されたため,先ほどのコードの以下の部分を書き換えることができます.

 // for (std::vector<int>::iterator it = v.begin(); it != v.end(); it++)
 for (auto it = v.begin(); it != v.end(); it++)

アルゴリズム

C++にはC言語にない機能として標準ライブラリにさまざまなアルゴリズムがあります. たとえばsort機能などがあります.以下のようにint型の配列をソートすることができます.

#include <algorithm>
#include <iostream>

int main() {
   int t[] = {3, 2, 1};
   sort(t, t + 3); // ソート
   return 0;
}