boost multi_index_container 多索引容器的使用
多索引容器 multi_index_container
为什么要使用multi_index_container
相信想必大家在实际开发中一定多少会遇到一些的问题,我需要创建一个可以索引的容器,例如map,set 但是无论map还是set 都是单索引的,例如建立一个类,类里有多个成员变量我们都要对应的索引便于查找 例如:
class Ticket
{
public:int ticketHeight;//块高uint256 ticketTxHash;//票hashCAmount ticketPrice;//当前票的票价CBitcoinAddress ticketAddress;//买票的地址Ticket();Ticket(const Ticket& ticket);Ticket(int ticketHeight, uint256 ticketTxHash, CAmount ticketPrice, CBitcoinAddress ticketAddress);void operator=(Ticket & ticket){this->ticketAddress = ticket.ticketAddress;this->ticketHeight = ticket.ticketHeight;this->ticketPrice = ticket.ticketPrice;this->ticketTxHash = ticket.ticketTxHash;}bool operator==(Ticket ticket){if (this->ticketAddress == ticket.ticketAddress &&this->ticketHeight == ticket.ticketHeight &&this->ticketTxHash == ticket.ticketTxHash &&this->ticketPrice == ticket.ticketPrice){return true;}return false;}std::string toString();~Ticket();
private:};
我需要对ticketHeight,ticketTxHash 经行排序索引,如果只是使用map,set构建索引的话,只能对应一种索引,ticketTxHash 或者ticketHeight,而我们需要使用两个map或者set才可以完成对应的需求,那么有没有一种结构可以对应两个排序索引——答案是有的 就是我们要说的 boost库中的 multi_index_container
下面就来说一下 multi_index_container 的基本使用,以及我遇到的坑,希望大家不要踩到;
创建
multi_index_container可以看作加载在内存中的数据库,不多说直接上代码
struct ticket_tx_hash {};//为排序索引后表建立的表明()struct ticket_height {};typedefboost::multi_index_container<Ticket, //此处为你要排序的成员类名indexed_by< //indexed_by<...> 中填写索引规则ordered_unique< //ordered_unique 类比数据库中的主键为唯一索引,ordered默认升序,还有其他顺序下面会做具体描述//tag<...> 指定表名 需要声明即上面的结构体名//BOOST_MULTI_INDEX_MEMBER boost的宏,表示在目标中选取成员作为排序依据 //(Ticket, uint256, ticketTxHash) Ticket:容器成员 uint256:排序依据的类型 ticketTxHash :排序依据tag<ticket_tx_hash>, BOOST_MULTI_INDEX_MEMBER(Ticket, uint256, ticketTxHash)>,ordered_non_unique<//非唯一索引——可与存在多个tag<ticket_height>, BOOST_MULTI_INDEX_MEMBER(Ticket, int, ticketHeight)>>> ticketpool_set;ticketpool_set ticket_pool;
这样就完成了一个多索引容器类型ticketpool_set的建立,接着实例化了一个ticketpool_set类型的ticket_pool
补充1 :排序不止ordered_unique/ordered_non_unique一种,还有hashed_unique,下面是一段比特币mempool代码,以及指定排序规则
typedef boost::multi_index_container<CTxMemPoolEntry,boost::multi_index::indexed_by<// hashed_unique 按照hash排序boost::multi_index::hashed_unique<mempoolentry_txid, SaltedTxidHasher>,//指定排序规则 CompareTxMemPoolEntryByDescendantScoreboost::multi_index::ordered_non_unique<boost::multi_index::tag<descendant_score>,boost::multi_index::identity<CTxMemPoolEntry>,CompareTxMemPoolEntryByDescendantScore>,。。。。//省略
不同索引的表 以及 迭代器
两种取迭代器的方法(固定格式)
//index<ticket_tx_hash>指定tag 为 ticket_tx_hash的表的迭代器typedef ticketpool_set::index<ticket_tx_hash>::type::iterator Ticketiter;//index<0> 去上述排序规则中的第一条规则,实际效果和index<ticket_tx_hash>一样,// 规则序号自0 开始//typedef ticketpool_set::index<0>::type::iterator Ticketiter;
取表
//取出规则需要为0的表,
ticketpool_set::index<ticket_tx_hash>::type & ticket_tx_hash_pool = this->ticket_pool.get<0>();
//取出规则需要为ticket_tx_hash的表,
ticketpool_set::index<ticket_tx_hash>::type & ticket_tx_hash_pool = this->ticket_pool.get<ticket_tx_hash>();
补充2: 在迭代的时候迭代器取出来的为const 类型的,需要注意,通过const_cast可以去除const
使用
ticketPool类完整版
class ticketPool
{
public:ticketPool();~ticketPool();struct ticket_tx_hash {};struct ticket_height {};typedefboost::multi_index_container<Ticket,indexed_by<ordered_unique<tag<ticket_tx_hash>, BOOST_MULTI_INDEX_MEMBER(Ticket, uint256, ticketTxHash)>,ordered_non_unique<tag<ticket_height>, BOOST_MULTI_INDEX_MEMBER(Ticket, int, ticketHeight)>>> ticketpool_set;ticketpool_set ticket_pool;typedef ticketpool_set::index<ticket_tx_hash>::type::iterator Ticketiter;//typedef ticketpool_set::index<0>::type::iterator Ticketiter;bool ticketPush(Ticket& ticket);bool ticketDel(Ticket ticket);bool ticketDelByHeight(int height);void print_ticket(){for (Ticketiter ticketiter = this->ticket_pool.get<ticket_tx_hash>().begin(); ticketiter != this->ticket_pool.get<ticket_tx_hash>().end(); ticketiter++){Ticket ticket = *ticketiter;std::cout << ticket.toString() << std::endl;}std::cout << "------------------------------------------------------------------------" << std::endl;for (ticketpool_set::index<ticket_height>::type::iterator ticketiter = this->ticket_pool.get<ticket_height>().begin(); ticketiter != this->ticket_pool.get<ticket_height>().end(); ticketiter++){Ticket ticket = *ticketiter;std::cout << ticket.toString() << std::endl;}}//Ticket ticketAt(unsigned int index);private:};
增加(insert)
bool ticketPool::ticketPush(Ticket& ticket)
{this->ticket_pool.insert(ticket);return true;
}
当然插入之后,表会自动按排序规则更新,完全不用担心
删除 (erase)
ticket_tx_hash_pool.erase(ticketiter);
补充3:如果拿原有表直接删除是不行的,因为原表的为const,这里我是取出表之后在经行删除的。完整代码如下
bool ticketPool::ticketDel(Ticket ticket)
{ticketpool_set::index<ticket_tx_hash>::type & ticket_tx_hash_pool = this->ticket_pool.get<ticket_tx_hash>();for (Ticketiter ticketiter = this->ticket_pool.get<ticket_tx_hash>().begin(); ticketiter != this->ticket_pool.get<ticket_tx_hash>().end(); ticketiter++){//上面说了迭代器取出的是有const属性的,所以(*ticketiter)==ticket,会导致boost编译时出错,也有一部分原因是我重载== 号的时候时没有const属性的原因if (ticket == (*ticketiter)){ticket_tx_hash_pool.erase(ticketiter);return true;}}return false;
}
补充4 : 删除当然也可以删除一段内容(需要排序后的表),内容为两个迭代器之间的所有东西
bool ticketPool::ticketDelByHeight(int height)
{ticketpool_set::index<ticket_height>::type::iterator pend;ticketpool_set::index<ticket_height>::type::iterator pbegin = this->ticket_pool.get<1>().begin();while (pbegin != this->ticket_pool.get<ticket_height>().end()){if (pbegin->ticketHeight == height){break;}pbegin++;} pend = pbegin;while (pend->ticketHeight ==height && pend!= this->ticket_pool.get<ticket_height>().end()){pend++;}this->ticket_pool.get<ticket_height>().erase(pbegin, pend);return true;
}
修改(replace和modify)
因为我时在写区块链底层代码,所以我的代码里没有修改这个方法,所以就简单介绍一下修改方法。
修改分为两种方法replace和modify(由ordered_index索引器提供)
可以自己去看boost文档boost中文文档链接
查看(find)
CBitcoinAddress a1("qfWkAzh1DqJTtNegiY7sEQteJUPNxKHEER");
icketpool_set::index<ticket_height>::type::iterator it = this->ticket_pool.get<1>().find(a1);
最后附上完整的代码及测试代码和测试结果,需要结合比特币代码看下,如果只是学习使用就够了
// ticketpool.h
#pragma once#include "uint256.h"
#include "base58.h"
#include "amount.h"#include <list>
#include <string>#include "boost/multi_index/identity.hpp"
#include "boost/multi_index/member.hpp"#include "boost/multi_index_container.hpp"
#include "boost/multi_index/ordered_index.hpp"
#include "boost/multi_index/hashed_index.hpp"
#include <boost/multi_index/sequenced_index.hpp>
using boost::multi_index_container;
using namespace boost::multi_index;class Ticket
{
public:int ticketHeight;//块高uint256 ticketTxHash;//票hashCAmount ticketPrice;//当前票的票价CBitcoinAddress ticketAddress;//买票的地址Ticket();Ticket(const Ticket& ticket);Ticket(int ticketHeight, uint256 ticketTxHash, CAmount ticketPrice, CBitcoinAddress ticketAddress);void operator=(Ticket & ticket){this->ticketAddress = ticket.ticketAddress;this->ticketHeight = ticket.ticketHeight;this->ticketPrice = ticket.ticketPrice;this->ticketTxHash = ticket.ticketTxHash;}bool operator==(Ticket ticket){if (this->ticketAddress == ticket.ticketAddress &&this->ticketHeight == ticket.ticketHeight &&this->ticketTxHash == ticket.ticketTxHash &&this->ticketPrice == ticket.ticketPrice){return true;}return false;}std::string toString();~Ticket();
private:};class ticketPool
{
public:ticketPool();~ticketPool();struct ticket_tx_hash {};struct ticket_height {};typedefboost::multi_index_container<Ticket,indexed_by<ordered_unique<tag<ticket_tx_hash>, BOOST_MULTI_INDEX_MEMBER(Ticket, uint256, ticketTxHash)>,ordered_non_unique<tag<ticket_height>, BOOST_MULTI_INDEX_MEMBER(Ticket, int, ticketHeight)>>> ticketpool_set;ticketpool_set ticket_pool;typedef ticketpool_set::index<ticket_tx_hash>::type::iterator Ticketiter;//typedef ticketpool_set::index<0>::type::iterator Ticketiter;bool ticketPush(Ticket& ticket);bool ticketDel(Ticket ticket);bool ticketDelByHeight(int height);void print_ticket(){for (Ticketiter ticketiter = this->ticket_pool.get<ticket_tx_hash>().begin(); ticketiter != this->ticket_pool.get<ticket_tx_hash>().end(); ticketiter++){Ticket ticket = *ticketiter;std::cout << ticket.toString() << std::endl;}std::cout << "------------------------------------------------------------------------" << std::endl;for (ticketpool_set::index<ticket_height>::type::iterator ticketiter = this->ticket_pool.get<ticket_height>().begin(); ticketiter != this->ticket_pool.get<ticket_height>().end(); ticketiter++){Ticket ticket = *ticketiter;std::cout << ticket.toString() << std::endl;}}//Ticket ticketAt(unsigned int index);private:};
//ticketpool.cpp#include "ticketpool.h"
#include "tinyformat.h"
Ticket::Ticket()
{
}Ticket::Ticket(const Ticket& ticket)
{this->ticketAddress = ticket.ticketAddress;this->ticketHeight = ticket.ticketHeight;this->ticketPrice = ticket.ticketPrice;this->ticketTxHash = ticket.ticketTxHash;
}Ticket::Ticket(int ticketHeight, uint256 ticketTxHash, CAmount ticketPrice, CBitcoinAddress ticketAddress)
{this->ticketAddress =ticketAddress;this->ticketHeight = ticketHeight;this->ticketPrice = ticketPrice;this->ticketTxHash = ticketTxHash;}Ticket::~Ticket()
{
}std::string Ticket::toString()
{std::string ticketStr;ticketStr += strprintf("ticket info:\t ticketAddress = %s \t ticketHeight = %d \t ticketPrice = %d \t ticketTxHash = %s \n",this->ticketAddress.ToString(),this->ticketHeight,this->ticketPrice,this->ticketTxHash.ToString());return ticketStr;
}ticketPool::ticketPool()
{
}ticketPool::~ticketPool()
{
}bool ticketPool::ticketPush(Ticket& ticket)
{this->ticket_pool.insert(ticket);return true;
}bool ticketPool::ticketDel(Ticket ticket)
{ticketpool_set::index<ticket_tx_hash>::type & ticket_tx_hash_pool = this->ticket_pool.get<ticket_tx_hash>();for (Ticketiter ticketiter = this->ticket_pool.get<ticket_tx_hash>().begin(); ticketiter != this->ticket_pool.get<ticket_tx_hash>().end(); ticketiter++){if (ticket == (*ticketiter)){ticket_tx_hash_pool.erase(ticketiter);return true;}}return false;
}bool ticketPool::ticketDelByHeight(int height)
{ticketpool_set::index<ticket_height>::type::iterator pend;ticketpool_set::index<ticket_height>::type::iterator pbegin = this->ticket_pool.get<1>().begin();twhile (pbegin != this->ticket_pool.get<ticket_height>().end()){if (pbegin->ticketHeight == height){break;}pbegin++;} pend = pbegin;while (pend->ticketHeight ==height && pend!= this->ticket_pool.get<ticket_height>().end()){pend++;}this->ticket_pool.get<ticket_height>().erase(pbegin, pend);return true;
}Ticket ticketPool::ticketAt(unsigned int index)
{Ticketiter ticketiter = this->ticket_pool.get<ticket_tx_hash>().begin();if (index >= this->ticket_pool.size() ){throw std::runtime_error("ticket index error");}for (unsigned int i = 0 ; i < index ; i++){ticketiter++;}return *ticketiter;}
#include <stdio.h>
#include <iostream>
#include <primitives/block.h>
#include "ticketpool.h"
#include "base58.h"
int main(int argc, char* argv[])
{printf("hello world!\n");CBitcoinAddress a1("qfWkAzh1DqJTtNegiY7sEQteJUPNxKHEER");CBitcoinAddress a2("qKyMFKqhTAUu6ka9t2nZ1bxYz1bAYfmuVN");CBitcoinAddress a3("qL3VbDUTbtm8MN9ii8Xm5DZe25LvYhxoe1");CBitcoinAddress a4("qMZupjWUQKFJpY63SvPrqz7R791CYUCsFn");CBitcoinAddress a5("qTLkcQALhxsqetNvkwdQ87XeVaeYoWcHx7");CBitcoinAddress a6("qRpj8gKWNHcYN3HjPpi5p8912fntEX6x5p");uint256 u1;u1.SetHex("0x1c2f3fb3ada4973384f3b1e84267fe7e80888a121b14480b74ed708329370deb");uint256 u2;u2.SetHex("0x2c2f3fb3ada4973384f3b1e84267fe7e80888a121b14480b74ed708329370deb"); uint256 u3;u3.SetHex("0x7c2f3fb3ada4973384f3b1e84267fe7e80888a121b14480b74ed708329370deb"); uint256 u4;u4.SetHex("0x4c2f3fb3ada4973384f3b1e84267fe7e80888a121b14480b74ed708329370deb");uint256 u5;u5.SetHex("0x5c2f3fb3ada4973384f3b1e84267fe7e80888a121b14480b74ed708329370deb");uint256 u6;u6.SetHex("0x6c2f3fb3ada4973384f3b1e84267fe7e80888a121b14480b74ed708329370deb");std::cout << " a " << std::endl;Ticket t1(1,u1,1000, a1);std::cout << " a " << std::endl;Ticket t2(1, u2, 1000, a2);Ticket t3(2, u3, 1000, a3);Ticket t4(2, u4, 1000, a4);Ticket t5(3, u5, 1000, a5);Ticket t6(2, u6, 1000, a6);std::cout <<" " <<t1.toString() << std::endl;ticketPool pool;pool.ticketPush(t1);pool.ticketPush(t2);pool.ticketPush(t3);pool.ticketPush(t4);pool.ticketPush(t5);pool.ticketPush(t6);pool.print_ticket();std::cout << " \n " << pool.ticketAt(2).toString() << std::endl;std::cout << " \n " << pool.ticketAt(1).toString() << std::endl;std::cout << " \n " << pool.ticketAt(0).toString() << std::endl;//pool.ticketDel(t4);pool.ticketDelByHeight(2);std::cout << " -------------delete --------------------- " << std::endl;pool.print_ticket();return 0;}
boost multi_index_container 多索引容器的使用相关推荐
- 多索引表 (1)boost::multi_index多索引容器
1. 定义 一个名为multi_index_container的类模板,它支持构建容器来维护一个或多个具有不同排序和访问语义的索引. 每一个multi_index都相当于传统数据库的一个数据表(tab ...
- boost::detail模块fwd容器的测试程序
boost::detail模块fwd容器的测试程序 实现功能 C++实现代码 实现功能 boost::detail模块fwd容器的测试程序 C++实现代码 #include <boost/det ...
- Boost:基于不同容器的有界缓冲区比较
Boost:基于不同容器的有界缓冲区比较 实现功能 C++实现代码 实现功能 基于不同容器的有界缓冲区比较 C++实现代码 #include <boost/circular_buffer.hpp ...
- Boost学习之指针容器--pointer_container
有时,我们可能需要一个包含指针的容器.比如存放一些不可拷贝的对象或者想在容器里存放基类以实现多态.尽管我们可以直接定义存放指针的STL容器,不过这样并不方便,我们得处处小心,在清空或删除容器里的元素时 ...
- boost any 实现万能容器_全面剖析 C++ Boost 智能指针!| CSDN 博文精选
作者 | .NY&XX 责编 | 屠敏 出品 | CSDN 博客 为什么要使用智能指针 C++没有提供类似JAVA的垃圾回收机制,因此Boost可以通过智能指针来管理内存避免一些问题.C++继 ...
- boost多个关键字索引multi_index_container
根据不同的索引排序结构体.其中tag的意思是指定一个标记,如果不指定的话默认是从0开始,以下例子展示了这两种情况 代码: [cpp] view plain copy #include <stri ...
- 所有的 Boost 库文档的索引
入门 工具 网站 新闻 社区 常见问题 更多的信息 按字母顺序列出的库 按类别列出的库 算法 破碎的编译器的解决方法 并发编程 容器 正确性和测试 数据结构 特定于域的 函数对象和高阶编程 泛型编程 ...
- Boost.MultiIndex 使用序列索引的示例
Boost.MultiIndex 使用序列索引的示例 实现功能 C++实现代码 实现功能 Boost.MultiIndex 使用序列索引的示例 C++实现代码 #if !defined(NDEBUG) ...
- Boost.MultiIndex 使用随机访问索引的示例
Boost.MultiIndex 使用随机访问索引的示例 实现功能 C++实现代码 实现功能 Boost.MultiIndex 使用随机访问索引的示例 C++实现代码 #if !defined(NDE ...
最新文章
- 各位最近找我索要CCNA200-120的资源的同志些
- ubuntu上开启SSH服务
- PMCAFF微课堂「已结束」| 测试兄弟CEO揭秘如何提高创初团队的产品质量
- Win10+vs2013+Caffe静态库配置自己的工程
- java replaceall正则表达式_编写高性能Java代码的最佳实践
- 深度linux安装好上不了网,Deepin Linux 无法上网
- Android@Home与智能家居
- Java 程序读取properties文件
- 计算机网络知识点1——概述
- Tensorflow - 训练中出现 Nan 值
- linux free空闲内存用尽,Linux中显示空闲内存空间的free命令的基本用法,linuxfree...
- Mysql 锁机制详解
- Latex 表格 tabularx自动换行
- JS事件绑定的几种方式
- 【操作系统的目标和作用】
- Android开发 WebSocket
- unigui 验证码生成
- 使用爬虫下载汽车之家高清大图
- 蓝桥杯31天冲刺之二十三 [java]
- 创新产品 google glass
热门文章
- 用Qt写的平均绩点计算器
- firefox apk android,firefox nightly APK
- 二进制安全学习:最新指导Pwn环境搭建教程(安装Peda插件Pwn库 IDApro for Mac15)
- 014 | JavaWeb物流配货项目源码 | 大学生毕业设计 | 极致技术工厂
- 现在很多的APP都有“附近的人“功能,这是哪个知识实现的呢!
- jsp日报系统+mysql_工作日报系统软件(运行web程序+说明) 日报管理系统 - 下载 - 搜珍网...
- 在软件测试中如何搭建测试环境?
- 被传销洗脑是一种怎样的体验
- 在GridView中使用FindControl
- kafka Java客户端之consumer 流量控制 以及 Rebalance解析