boostマルチインデックスコンテナmulti_index_container


ゲーム開発でboostのmulti_に遭遇index_container、中国語をマルチインデックスコンテナに翻訳します.マルチインデックスコンテナとは何ですか?どうして彼を使うの?どうやって彼を使うの?以下、一つ一つ紹介します.
実際の開発では、mapを作成する必要があります.インデックスを作成するには、mapを作成する必要があります.たとえば、mapを作成する必要があります.しかし、私は学号でインデックスを作成する必要があります.名前でインデックスを作成する必要があります.しかし、std::mapはそのkey_しか使用できません.type(ここでは学号)をインデックスとして検索操作しますが、どうすればいいですか?「何が難しいの?」思いついた人もいるかもしれませんがvalue_type(名前)インデックスでもいいですか.関数を書いてこのmapを巡り、検索する名前を各pairのsecondと比較して、等しければ見つけられるのではないでしょうか.OK、そうです.これで問題を解決できますが、ただ粗雑に問題を解決するだけです.もしこのmapが大きいなら、検索するたびに遍歴しなければなりません.検索の平均複雑度はO(n/2)です.効率的なビジネスプロジェクトで使用すれば、性能テストが必要な日が風呂敷を片付けて人を歩く時だと信じています.
いくつかの効率的な方法について議論しましょう.標準ライブラリのstd::mapを使用します.今回は2つを作成し、1つは使用します.もう1つは、1人の学生に参加するたびに2つのmapに1つの要素を挿入する必要があります.削除するときも、この方法は最初の方法よりも優れています.少なくとも効率的な双方向検索ができます.しかし依然として欠陥があり、例えばメンテナンスが面倒で、操作するたびに2つのmapの対応関係を同時に配慮しなければならない.
このような簡単な双方向検索が必要な容器については、boost::bimapを使用すると簡単に問題を解決することができます.boost::bimapはこのような状況のために設計された容器です.もちろん、その強さはあなたの想像を超えているかもしれませんが、ここで議論しているのはそれではありません.私たちが実際の開発で遭遇した状況はもっと複雑です.たとえば、(学生情報は構造)のmapを作成するには、前の方法で少し面倒になります.例えば、学生情報構造のoperator==を再ロードしてインデックスを行う根拠など、損をする方法はここでは繰り返し議論しません.本章の本題に入り、multi_を使用しましょう.index_container、間違いなく、上記のすべての問題を簡単に解決することができます.
まず、Personについて説明する簡単な構造を作成します.
struct Person  {
	int id;
	int age;
	int hei;
	std::string name;
	Person(int i, int a, int h, std::string n)  {
		id = i;
		age = a;
		hei = h;
		name = n;
	}
	void Print() const {
		printf("name : %s, id is %d, age is %d, hei is %d
", name.c_str(), id, age, hei); } };

次に、複数のインデックスを持つコンテナを定義します.
typedef multi_index_container <
	Person, 
	indexed_by <
		ordered_unique >,
		ordered_non_unique >,
		ordered_non_unique >,
		ordered_non_unique >
	>
> PersonContainer;`


このコンテナは4つのインデックスを定義し、フィールド値が一意である場合があります.たとえば、実際にid番号を繰り返すことはできませんが、他の場合は同じです.
コンテナの挿入はstlコンテナの挿入と似ています.たとえば、次のようにします.
    PersonContainer pc;
	pc.insert(Person(2, 15, 170, "azhang"));
	pc.insert(Person(1, 17, 167, "dzhang"));
	pc.insert(Person(3, 18, 173, "czhang"));
	pc.insert(Person(0, 16, 167, "bzhang"));

その後、どのようにしてフィールドにインデックスを付けますか?簡単で、コンテナのgetメソッドを直接呼び出すと、このインデックスソートのコンテナが得られます.たとえば、pc.get<0>()はidフィールドインデックスのコンテナを返し、pc.get<1>()はageフィールドインデックスのコンテナを返します.ここでindexは、構造体のフィールドで定義された順序ではなく、コンテナを定義する順序であることに注意してください.
では、あるインデックスの順序が正の順序なのか逆の順序なのか、これはstlのmapのルールと一致し、基本的なタイプはデフォルトの小さい順から大きい順で、構造体は再ロードされます.
フィールドを定義する順序では、記憶が悪く、コードの変更に伴って送信が変化するという弊害があります.boostはこの点を考え、名前をインデックスとする方法を提供しました.
struct person_id{};
struct person_age{};
struct person_height{};
struct person_name{};

typedef multi_index_container <
	Person, indexed_by<
		ordered_unique, member >,
		ordered_non_unique, member >,
		ordered_non_unique, member >,
		ordered_non_unique, member >
	>
> PersonContainerTag;

容器の挿入方法は上と一致し、使用:pc 2.get().
完全なコードは次のとおりです.
#include 
#include 
#include 
#include  
#include 

using boost::multi_index_container;
using boost::multi_index::ordered_unique;
using boost::multi_index::ordered_non_unique;
using boost::multi_index::indexed_by;
using boost::multi_index::member;
using boost::multi_index::tag;


struct Age  {     //         
	Age(int a) :age(a) {}
	int age;
	bool operator a.age; }
};

struct Person  {
	int id;
	Age age;
	int hei;
	std::string name;
	Person(int i, Age a, int h, std::string n) :age(a) {
		id = i;
		hei = h;
		name = n;
	}
	void Print(const char* order) const {
		printf("order: %s, name is %s, id is %d, age is %d, hei is %d
", order, name.c_str(), id, age.age, hei); } }; typedef multi_index_container < Person, indexed_by < ordered_unique >, ordered_non_unique >, ordered_non_unique >, ordered_non_unique > > > PersonContainer; typedef PersonContainer::nth_index<0>::type IdIndex; typedef PersonContainer::nth_index<1>::type AgeIndex; typedef PersonContainer::nth_index<3>::type NameIndex; struct person_id{}; struct person_age{}; struct person_height{}; struct person_name{}; typedef multi_index_container < Person, indexed_by< ordered_unique, member >, ordered_non_unique, member >, ordered_non_unique, member >, ordered_non_unique, member > > > PersonContainerTag; int main() { PersonContainer pc; pc.insert(Person(2, Age(15), 170, "azhang")); pc.insert(Person(1, 17, 167, "dzhang")); pc.insert(Person(3, 18, 173, "czhang")); pc.insert(Person(0, 16, 167, "bzhang")); IdIndex& ids = pc.get<0>(); // , , for (auto it = ids.begin(); it != ids.end(); ++it) { it->Print("id"); } printf("

"); AgeIndex& ages = pc.get<1>(); for (auto it = ages.begin(); it != ages.end(); ++it) { it->Print("age"); } printf("

"); NameIndex& names = pc.get<3>(); for (auto it = names.begin(); it != names.end(); ++it) { it->Print("name"); } PersonContainerTag pc2; pc2.insert(Person(2, Age(15), 170, "azhang")); pc2.insert(Person(1, 17, 167, "dzhang")); pc2.insert(Person(3, 18, 173, "czhang")); pc2.insert(Person(0, 16, 167, "bzhang")); auto& names2 = pc2.get(); for (auto it = names2.begin(); it != names2.end(); ++it) { it->Print("names2"); } return 0; }

他にも挿入方法があります.
AgeIndex& ages = pc.get<1>();
auto p = ages.insert(Person(3, 19, 171, "ezhang")).first;

  ,  p      Person(3, 19, 171, "ezhang") ,            。  id      , 3    ,      ,    id 3   。

        stl::pair :
std::pair<:multi_index::detail::bidir_node_iterator std::allocator=""> > > > > >, bool>

       C++       ,         ?

     ,         ,        ,         ,bool  false,   p       。


 
参照先:
https://blog.csdn.net/liuqiuyuewo/article/details/75332345
https://blog.csdn.net/lsjseu/article/details/43370707
https://blog.csdn.net/lee353086/article/details/40706669