boost::ptr_map の使い方
boost::ptr_mapの使い方が,どこを探してもはっきりとは載っていなかったのでメモ。 boostのバージョンは1.41。 必要最低限の使い方です。
下準備
boost::ptr_mapを使うためには,boost/ptr_container/ptr_map.hpp をインクルードする必要がある。
#include <boost/ptr_container/ptr_map.hpp>
また,説明するためにこんなクラスを用意。
/** * 基底クラス。 * 純粋仮想関数を含んでいるのでインスタンスかはできない(インターフェイス)。 */ class BaseContainer { public: virtual void mes() = 0; }; /** * コンテナクラス。 * BaseContainerを継承。 * 値の保持と,何を保持しているかを表示するメソッド。 */ template <class T> class Container : public BaseContainer { private: T value; public: Container(T value) { this->value = value; } void mes() { std::cout << "Container : value = " << value << std::endl; } };
boost::ptr_mapインスタンスの生成
キーをstd::string,値を BaseContainer としてインスタンスを生成。 値を BaseContainer にすることによって, Container インスタンスにどんな型を指定しても おなじ ptr_map インスタンスに突っ込めるっていうすんぽー。
boost::ptr_map<std::string, BaseContainer> Map m;
値の追加
生成した ptr_map インスタンスに値を追加する。
ptr_map はキー・値ともに参照で渡さないといけないらしいので,
一度変数に落としてから渡すようにする。
インスタンスを渡す場合には直接 new してもOK。
直接 new しないと実行時にエラーになります。
元のインスタンスと,ptr_mapに追加したインスタンス(両方とも同じ場所を指してる)が,
終了時に両方とも解放されるのが原因なんじゃないかと。
// 一度変数に落とさないとコンパイルエラー int key1 = 0; int key2 = 1; // ポインタとして宣言して new する // これをやると実行時に // error for object 0x7fff5fbff260: pointer being freed was not allocated // のようなエラーが出る(コンパイルは通る)。 // Container<int>* c; // c = new Container<int>(10); // m.insert(id1, c); // 直接 new する m.insert(id2, new Container<float>(20));
値の取り出し
boost::ptr_map インスタンスからオブジェクトを取り出す場合, std::map と同じように [] を使ってもうまくいかない。 扱ってるのがポインタだから?
// これだとコンパイルエラー
m[key1]
そこでメンバ関数の find() を使ってイテレータを取得してアクセスする。
// キー m.find(key1)->first; // 値 m.find(key1)->second; // Container.mes() の呼び出し m.find(key1)->second->mes();
値の削除
キーを指定して値を削除。 メモリの解放とかは勝手にやってくれるらしい。
// key1 の値を削除
m.erase(key1);
コードの全貌
今回のコードをつなげるとこんな感じになる。
#include <iostream> #include <string> #include <boost/ptr_container/ptr_map.hpp> class BaseContainer { public: virtual void mes() = 0; }; template <class T> class Container : public BaseContainer { private: T value; public: Container(T value) { this->value = value; } void mes() { std::cout << "Container : value = " << value << std::endl; } }; int main() { typedef boost::ptr_map<int, BaseContainer> m; std::string key1 = "n1"; std::string key2 = "n2"; m.insert(key2, new Container<int>(98)); m.insert(key2, new Container<float>(123.4)); std::cout << m.size() << std::endl; std::cout << m.find(key1)->first << std::endl; m.find(key1)->second->mes(); m.erase(key1); std::cout << m.size() << std::endl; return 0; }
出力
2 0 Container : value = 98 1