boost的multi_index的使用
生活随笔
收集整理的這篇文章主要介紹了
boost的multi_index的使用
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
這篇文章簡單介紹一下 boost 中十分實用的庫函數 --- 多重索引 multi_index ,它的底層結構是用來存放 結構體的 map?的數據結構,
但不同于 stl,boost 中普通的map,它可以根據用戶的需要來指定索引的類型,即 key 的值可以根據需要的不同而變化的。
multi_index的性能測試可參見博客:boost的multi_index性能測試
本示例演示功能如下:
1. multi_index_container的定義,聲明
2. 遍歷
3. 插入
4. 刪除
5. 修改
代碼實驗結果如下:
代碼如下:
#if !defined(NDEBUG) #define BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING #define BOOST_MULTI_INDEX_ENABLE_SAFE_MODE #endif#include <cstdio>#include <boost/multi_index_container.hpp> #include <boost/multi_index/member.hpp> #include <boost/multi_index/ordered_index.hpp> #include <boost/shared_ptr.hpp>#include <algorithm> #include <iostream> #include <iterator> #include <string>using boost::multi_index_container ; using namespace boost::multi_index ; using namespace std; using namespace boost;// 玩家信息 class CPlayer { public:CPlayer(int id, string name, int fight, int gold):id(id),name(name),fight(fight),gold(gold){ }void print() const{cout<<"id:"<<id<<", name:"<<name<<", fight:"<<fight<<", gold:"<<gold<<endl;}int id; // 唯一idstring name; // 名字int fight; // 戰斗力int gold; // 金幣 };//要將類CPlayer中的某個屬性字段設定為索引項,需定義與該屬性字段同名的空的結構體 struct id{}; struct name{}; struct fight{}; struct gold{};// BOOST_MULTI_INDEX_MEMBER宏 (創建表中的元素結構體名稱, 索引的類型, 索引的名稱 等于 tag<> 中設定的名稱)// 定義一個多索引容器類型 typedef multi_index_container <CPlayer, // 要將什么作為創建表的元素,傳入該結構體名稱indexed_by<ordered_unique<tag<id>, BOOST_MULTI_INDEX_MEMBER(CPlayer, int, id)>, // id為唯一索引,排序,與表項一一映射, tag<傳入剛剛定義好的 struct id{} 對應的名稱,類似數據庫表的主鍵ordered_non_unique<tag<name>, BOOST_MULTI_INDEX_MEMBER(CPlayer, string, name)>, // name為不唯一索引,排序ordered_non_unique<tag<fight>, BOOST_MULTI_INDEX_MEMBER(CPlayer, int, fight)>, // fight為不唯一索引,排序ordered_non_unique<tag<gold>, BOOST_MULTI_INDEX_MEMBER(CPlayer, int, gold)> // gold為不唯一索引,排序> >player_table;int main () {// 所有的玩家player_table allPlayer;allPlayer.insert(CPlayer(1, "zhao",90,1000)); // 趙allPlayer.insert(CPlayer(5, "qian",80,500)); // 錢allPlayer.insert(CPlayer(8, "sun",100,800)); // 孫allPlayer.insert(CPlayer(4, "li",90,2500)); // 李allPlayer.insert(CPlayer(2, "zhou",20,1200)); // 周allPlayer.insert(CPlayer(3, "wu",60,1000)); // 吳allPlayer.insert(CPlayer(7, "zheng",40,700)); // 鄭allPlayer.insert(CPlayer(6, "wang",100,800)); // 王/// 遍歷 // 使用get<index>方法得到玩家視圖,其拷貝構造函數是被保護的,所以只能返回引用// 謹記:這里的index是定義容器時的順序,而不是結構體中字段定義的順序,從0開始,所以3對應的gold屬性player_table::index<gold>::type& player_gold = allPlayer.get<3>();cout<<"以gold屬性排序的結果"<<endl;player_table::index<gold>::type::iterator iter_gold = player_gold.begin(); for(;iter_gold != player_gold.end();iter_gold++){iter_gold->print();}cout<<"\n"<<endl;// 得到以id屬性排序的玩家視圖(視圖與表的區別,視圖僅僅是表的一個映像,在系統中并不為視圖中的元素提供實際的存儲空間,類似于對象實體和指向對象的指針)player_table::index<id>::type& player_ID = allPlayer.get<id>(); cout<<"以id屬性排序的結果"<<endl;player_table::index<id>::type::iterator iter_ID = player_ID.begin(); for(;iter_ID != player_ID.end();iter_ID++) {iter_ID->print();}cout<<"\n"<<endl;// 得到以fight屬性排序的玩家視圖player_table::index<fight>::type& player_fight = allPlayer.get<fight>();cout<<"以fight屬性排序的結果"<<endl;player_table::index<fight>::type::iterator iter_score = player_fight.begin();for (;iter_score!=player_fight.end();iter_score++){iter_score->print();}cout<<"\n"<<endl;// 查找gold在[1000-2000]之間的玩家cout<<"查找gold在1000-2000之間的玩家"<<endl;player_table::index<gold>::type::iterator iter_low = allPlayer.get<gold>().lower_bound(1000);player_table::index<gold>::type::iterator iter_up = allPlayer.get<gold>().upper_bound(2000);while(iter_low != iter_up){iter_low->print();iter_low++;}cout<<"\n"<<endl;/// 插入 // insert() 函數返回std::pair<iterator,bool>對,成功時,iterator指向成功插入的對象,bool為true;失敗時iterator指向之前已存在的對象,bool為false// 成功:bool bSuc = allPlayer.insert(CPlayer(9, "zheng",200,2000)).second;// 鄭cout<<"插入成功結果值:"<<bSuc<<endl;// 失敗(因為ID為9的已存在):bSuc = allPlayer.insert(CPlayer(9, "zheng2",300,1000)).second;// 鄭2cout<<"插入失敗結果值:"<<bSuc<<endl;cout<<"\n"<<endl;/// 查找 // 得到以name屬性排序的玩家視圖,并執行find()函數cout<<"查找zhou"<<endl;player_table::index<name>::type::iterator iter_name = allPlayer.get<name>().find("zhou");if (iter_name != allPlayer.get<name>().end()){cout<< "find zhou player!"<< endl ;iter_name->print();}else{cout<<"cant't find zhou player!"<< endl ;}/// replace()修改 player_table::index<name>::type& player_name = allPlayer.get<name>();// 成功的replace()player_table::index<name>::type::iterator iter_wang = player_name.find("wang"); // 查找wangif (iter_wang != player_name.end()){cout<<"找到wang,結果如下"<<endl;iter_wang->print();CPlayer wang = *iter_wang;wang.gold = 1000; wang.id = 66; // 由于id是唯一的,但66不存在,修改后replace會返回成功bSuc = player_name.replace(iter_wang,wang);cout<<"修改wang的id為66的結果值:"<<bSuc<<endl;}// 失敗的replace()iter_wang = player_name.find("wang"); // 重新查找wangif (iter_wang != player_name.end()){cout<<"重新找到wang,結果如下"<<endl;iter_wang->print();CPlayer wang = *iter_wang;wang.gold = 1000; wang.id = 1; // 由于id是唯一的,但1已存在,修改后replace會返回失敗,此時replace可以保證容器不會發生任何變化bSuc = player_name.replace(iter_wang,wang);cout<<"修改wang的id為1的結果值:"<<bSuc<<endl;}// 注意:replace()會發生兩次賦值拷貝,如果結構很大并且使用的很頻繁,有可能會成為性能瓶頸cout<<"\n"<<endl;/// modify()修改 // 先定義修改的函數對象,這里以修改id為例class CModifyPlayer{public:CModifyPlayer(int id):m_id(id){}void operator()(CPlayer& player) {player.id = m_id;}private:int m_id;};// 成功的modify()player_table::index<name>::type::iterator iter_zheng = player_name.find("zheng"); // 查找zhengif (iter_zheng != player_name.end()){cout<<"找到zheng,結果如下"<<endl;iter_zheng->print();// 由于id是唯一的,但50不存在,修改后modify會返回成功bSuc = player_name.modify(iter_zheng,CModifyPlayer(50));cout<<"修改zheng的id為50的結果值:"<<bSuc<<endl;}cout<<"遍歷以name排序的視圖"<<endl;iter_name = player_name.begin(); for(;iter_name != player_name.end();iter_name++) {iter_name->print();}// 失敗的modify()iter_zheng = player_name.find("zheng"); // 重新查找zhengif (iter_zheng != player_name.end()){cout<<"重新找到zheng,結果如下"<<endl;iter_zheng->print();// 由于id是唯一的,但5已經存在,修改后modify會返回失敗,且本元素(iter_zheng)也會被刪掉!!!!bSuc = player_name.modify(iter_zheng,CModifyPlayer(5));cout<<"修改zheng的id為5的結果值:"<<bSuc<<endl;}cout<<"再次遍歷以name排序的視圖"<<endl;iter_name = player_name.begin(); for(;iter_name != player_name.end();iter_name++) {iter_name->print();}cout<<"\n"<<endl;/// 刪除 cout<<"刪除id為2的玩家"<<endl;player_table::index<id>::type::iterator iter_2 = player_ID.find(2);if (iter_2 != player_ID.end()){player_ID.erase(iter_2);}cout<<"再次遍歷以id排序的視圖"<<endl;iter_ID = player_ID.begin(); for(;iter_ID != player_ID.end();iter_ID++) {iter_ID->print();}cout<<"\n"<<endl;getchar();return 0 ; }?
總結
以上是生活随笔為你收集整理的boost的multi_index的使用的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: lua之弱引用table
- 下一篇: boost的multi_index性能测