User Tools

Site Tools


programming:cpp:container

This is an old revision of the document!


コンテナクラス

STL のコンテナクラスを使いこなせれば処理が楽になることは往々にしてある.
時間があれば適切なコンテナクラスを使うことに挑戦してみるのがよい

以下は自分が使ったもの

vector

C++ の reference はここにある.
要素の順序を保存するクラスであり,要素数が自動的に拡張される一次元配列のイメージ.
添字によるランダムアクセスが高速で行なえ,配列の最後尾に要素を追加していくイメージで使用することが多い.
末尾以外への挿入がメインの操作であったり,シーケンシャルアクセスの速さが必要な場合は list や deque を使うらしい.

for loop の回し方を以下に示しておく.

#include <vector>
 
int main(){
 
  std::vector<int> v = {1, 3, 4};
 
  for ( auto iv : v ) {
    std::cout << iv << std::endl;
  }
  // 1
  // 3
  // 4
  v.push_back(5);
 
  for ( auto itr = v.begin(); itr != v.end(); itr++ ) {
    std::cout << *itr << std::endl;
  }
  // 1
  // 3
  // 4
  // 5
 
  v.at(0) = 0;
 
  for ( int i = 0; i < v.size(); i++ ) {
    std::cout << v.at(i) << std::endl;
  }
  // 0
  // 3
  // 4
  // 5
 
  std::cout << v.front << ", " << v.back << std::endl;
  // 0, 5
 
}

その他resize, empty, reserve, clear, shrink_to_fit などの使い方を調べてみるとよい.

array

C++ の reference はここにある.
要素の順序を保存するクラスであり,vector と違って要素数が決まっている.
個人的には vector を使っていればよいと思うので,あまり使っていない.
ROOT では array はバグの温床なので使わないほうがよい.

set

C++ の reference はここにある.
数学における集合に相当し,ユニークな要素を収納するクラス.
ある要素があるかないか」という特徴から探索をすることに特化しており,次の map において要素自身がキーとなっていることに相当する.
「コンテナの何番目」という特徴から探すのであれば vector や array がよい.
要素はユニークでなければならず,複数の要素を許すには multiset を用いる.

たとえば std::set<std::pair<B2EmulsionSummary*, B2EmulsionSummary* > > linklets としてあるグループに含まれる linklet の set を使った.
linklet は重複が考えられるが,重複する linklet を考える意味はなく,また順番よりもある linklet の有無が気になることがあるため. (もちろんアルゴリズムによる)
なお,こんな長い型は本来は適当に以下のように typedef するべきである.

typedef std::set<std::pair<B2EmulsionSummary*, B2EmulsionSummary* > > B2PairSet;

set は二分木で探索する際に要素の順序を用いるため,少なくとも不等号が必要. (default は less<Key>)
自作クラスについてはoperator< を定義する必要がある.
operator のオーバーロードの仕方はここを参照.

map

C++ の reference はここにある.
ユニークな要素をキーと関連付けて収納するクラス.
要素に対して「あるキーを持っている」という特徴から探索をすることに特化したコンテナクラス.
「コンテナの何番目」という特徴から探すのであれば vector や array がよい.
キーと要素は 1:1 対応でなければならず,あるキーに対して複数の要素を許すには multimap を用いる.

たとえば std::map<int, B2TrackSummary* > track_id_map として track id と B2 class の map を使った.
これは track->GetTrackId() とは別の id が emulsion 側とのインターフェースのために振られているためで,解析のフローを改良するべきだという意見は大いにある.

map は二分木で探索する際にキーの順序を用いるため,少なくとも不等号が必要. (default は less<Key>)
自作クラスについてはoperator< を定義する必要がある.
operator のオーバーロードの仕方はここを参照.

#include <iostream>
#include <map>
 
int main (int argc, char *argv[]) {
 
  map<int, std::string> month_map;
 
  // 要素の追加は make_pair を用いて行う
  month_map.insert(std::make_pair(1, "January"));
  month_map.insert(std::make_pair(2, "February"));
  month_map.insert(std::make_pair(3, "March"));
  // 同じキーに対応する要素は追加されない
  month_map.insert(std::make_pair(3, "April"));
 
  for ( auto itr = month_map.begin(); itr != month_map.end(); itr++ ) {
    std::cout << (*itr).first << "月 : " << (*itr).second << std::endl;
  }
  // 1月 : January
  // 2月 : February
  // 3月 : March
 
  // キーの値で月を探索
  std::string second_month = month_map.at(2);
  std::cout << second_month << std::endl;
  // February
 
  std::exit(0);
 
}

multimap

C++ の reference はここにある.
map において一つのキーに対して複数の要素を許すようにしたもの.

unordered_multimap

std でも boost でもよい

unordered なコンテナを使う際には等号とハッシュ関数が必要.
自作クラスについてはこれらを定義する必要がある.
boost の unordered_multimap の例を以下に示す. hash の作り方

programming/cpp/container.1651749521.txt.gz · Last modified: 2022/05/05 11:18 by odagawa