努力学习的boost ::侵入Q2 [英] Trying to learn boost::intrusive Q2
问题描述
如果我去掉这些
// BaseList baselist;
//会员会员;
外循环并注释掉崩溃的循环内的人。我需要能够有任何循环外的baselist(和会员)。这是如何实现的?
修改
我想在它来解决实际问题的最简单的形式是这样的。
我想有
MyClass的
的一个std ::向量,称之为AllThingsBunchedTogether。
我也希望有BaseList
的一个std ::向量,称之为AllThingsS preadOut。
所以
- AllThingsBunchedTogether可能包含(对于紧凑的缘故只是
anInt1
部分):1,2,1,10,2,3,4 ,4,5,9,10,10
。
- AllThingsS preadOut可能包含在[1]
1,1
在[2]2,2(零不用于现在)
在[3]3
在[4]4,4
在[5]5
在[9]9
在[10]10,10,10
。
请注意,本身并不存储在号码
BaseList
,但如在MyClass的
(1 , 约翰)。
目前[1]也可能是迈克,约翰,在[2]也可能是迈克,Dagobart在[3]
约翰在... [10]约翰麦克Dagobart等,使在那里没有重复
在每个任何BaseList
在AllThingsS preadOut [我],因为每个MyClass的
BaseList
散列不同的值(anInt1 +姓名
)。
在本质上,
anInt1
讲述其中MyClass的
住在AllThingsS preadOut,但anInt1 +名称
保证在每个独特BaseList
。
这样的想法是,AllThingsS preadOut是一个vector
BaseList
,其中每个BaseList
在矢量位置是类似的事情的清单。
然后,当我从AllThingsBunchedTogether删除的东西(而不是明确的,而是由一个搜索除去像下面IsMarkedToDelete的code部分项目),它们将自动从相应的AllThingsS preadOut消失。
AllThingsS preadOut作为一种用于AllThingsBunchedTogether,具有侵入性语义。 AllThingsBunchedTogether允许通过[]超快的访问。
块引用>结束修改
的#include<矢量>
#包括LT&;&iostream的GT;#包括LT&;升压/侵入/ list.hpp>使用空间boost ::侵入;MyClass类:公共list_base_hook< link_mode< auto_unlink>> //这是一个推导挂钩
{
上市:
性病::字符串名称;
布尔bIsMarkedToDelete;
INT anInt1;
上市:
list_member_hook< link_mode< auto_unlink>> member_hook_; //这是一个成员挂钩 MyClass的(性病::字符串n,int i)以:名(n),anInt1(I),bIsMarkedToDelete(假){}
};布尔IsMarkedToDelete(常量MyClass的&放大器; O)
{
返回o.bIsMarkedToDelete;
}//定义将使用公共基类钩子保存MyClass的名单
的typedef列表< MyClass的,constant_time_size<假>> BaseList;//定义将使用公有成员钩子保存MyClass的名单
的typedef列表< MyClass的,
member_hook&所述; MyClass的,list_member_hook&所述; link_mode&下; auto_unlink>>中&放大器; MyClass的:: member_hook_>中
constant_time_size<假> >会员;诠释的main()
{
布尔做= FALSE;
的std ::矢量<&MyClass的GT;值; 性病::字符串名称[] = {约翰,迈克,Dagobart}; // BaseList baselist;
//会员会员; INT I = 0;
而(!完成)
{
//创建几个MyClass的对象,每一个不同的值 为(中间体J = 0; J&下; 11; ++ j)条
values.emplace_back(地名[J%3],J); BaseList baselist;
会员会员; //现在将其插入T-他在基地挂钩列表反序
为(自动急症:值)
{
baselist.push_front(E);
memberlist.push_back(E);
} //现在测试列表
自动RBIT(baselist.rbegin());
自动MIT(memberlist.begin());
自动它(values.begin()),itend(values.end()); //测试插入在基座钩列表中的对象
为(;!它= itend ++吧,++ RBIT)
{
如果(安培;!* RBIT =放大器; *它)
返回1;
}
//测试插入构件钩列表中的对象
对于(IT = values.begin();它= itend;!++中,++ MIT)
{
如果(安培;!* MIT =放大器; *它)
返回1;
}
#如果0
为(自动急症:值)
性病::法院LT&;< e.anInt1<< \\ n; 为(自动急症:baselist)
性病::法院LT&;< e.anInt1<< \\ n; 为(自动急症:会员)
性病::法院LT&;< e.anInt1<< \\ n;#ENDIF // 0 如果(2 == I)
{
为(自动急症:值)
性病::法院LT&;< e.name<< \\ n; 为(自动急症:值)
{
如果(迈克== e.name)
e.bIsMarkedToDelete = TRUE;
} values.erase(
性病::的remove_if(values.begin(),values.end(),IsMarkedToDelete),values.end());
}
如果(ⅰ++→3)
{
values.clear();
做= TRUE;
} 性病::法院LT&;< \\ n;
性病::法院LT&;< values.size()&所述;&下; \\ n;
性病::法院LT&;< baselist.size()&所述;&下; \\ n;
性病::法院LT&;< memberlist.size()&所述;&下; \\ n;
}
}
解决方案我已经看到了它晚了,但不管怎么说,这里有云:
您描述一下比赛的究竟的
MyClass的
元素的侵入哈希表的实现,其中
anInt1
是哈希(中的斗的标识符)的元素- 桶列表被实现为链表
平等是指平等
(anInt1,名称)
块引用>
所以真的,你的程序可能的只是的是:<大骨节病> 住在Coliru 骨节病>
的std :: unordered_set&LT; MyClass的&GT;值{
{约翰,0},{迈克,1},{Dagobart,2},
{约翰,3},{迈克,4},{Dagobart,5},
{约翰,6},{迈克,7},{Dagobart,8},
{约翰,9},{迈克,10},
};的for(int i = 0; I&LT; = 3; ++ I){
如果(2 == I){
为(自动急症:值)的std ::法院LT&;&LT; e.name&LT;&LT; ;性病::法院LT&;&LT; \\ n;
为(自动急症:值)e.bIsMarkedToDelete | =(迈克== e.name); 为(自动它=开始(值)!=它结束(值)){
如果(IT-&GT; bIsMarkedToDelete)IT = values.erase(它);
其他++中;
}
} 性病::法院LT&;&LT; 我=&LT;&LT; I&LT;&LT; values.size():&所述;&下; values.size()&所述;&下; \\ n;
}
values.clear();
性病::法院LT&;&LT; 做的\\ n;
如果你真的想连续的存储,我只能假设你想这对性能
在不要想用指针而不是对象,因为这只是否定了内存布局(AllThingsBunchedTogether)利益,你会与<$ C $更好C> unordered_set 或
unodered_map
如上在不要要使用
auto_unlink
模式,因为它削弱性能(通过做不受控制删除触发器,通过抑制恒时间尺寸()
,并通过创建线程安全问题)相反,你应该使用上述战略思考,而是用
的boost ::侵入:: unordered_set
,而不是看的http://www.boost.org/doc/libs/1_57_0/doc/html/intrusive/unordered_set_unordered_multiset.html下面,又是一个证明的概念:
<大骨节病> 住在Coliru 骨节病>
的#include&LT;矢量&GT;
#包括LT&;&iostream的GT;
#包括LT&;升压/侵入/ unordered_set.hpp&GT;
#包括LT&;矢量&GT;
//#包括&lt;功能&GT;
//#包括LT&;&算法GT;命名空间BIC =的boost ::侵入;结构MyClass的:BIC :: unordered_set_base_hook&LT; BIC :: link_mode&LT; BIC :: auto_unlink&GT;&GT;
{
性病::字符串名称;
INT anInt1;
可变布尔bIsMarkedToDelete; MyClass的(标准::字符串名称,int i)以:姓名(名称),anInt1(I),bIsMarkedToDelete(假){} 布尔运算符==(const的MyClass的放大器和O)const的{返回anInt1 == o.anInt1&放大器;&安培;命名== o.name; } 结构散列器{为size_t运算符()(MyClass的常量和放大器; O)const的{返回o.anInt1; }};
};BIC的typedef :: unordered_set&LT; MyClass的,BIC ::散列&LT; MyClass的::散列器&gt;中BIC :: constant_time_size&LT;假&gt; &GT;哈希表;诠释主(){ 的std ::矢量&lt;&MyClass的GT;值{
MyClass的{约翰,0},{MyClass的迈克,1},{MyClass的Dagobart,2},
MyClass的{约翰,3},{MyClass的迈克,4},{MyClass的Dagobart,5},
MyClass的{约翰,6},{MyClass的迈克,7},{MyClass的Dagobart,8},
MyClass的{约翰,9},{MyClass的迈克,10},
}; 哈希表:: bucket_type桶[100];
哈希表哈希表(values.begin(),values.end(),哈希表:: bucket_traits(桶,100)); 的for(int i = 0; I&LT; = 3; ++ I){
如果(2 == I){
为(自动急症:值)的std ::法院LT&;&LT; e.name&LT;&LT; ;性病::法院LT&;&LT; \\ n;
为(自动急症:值)e.bIsMarkedToDelete | =(迈克== e.name); values.erase(性病::的remove_if(开始(值),端(值)的std ::的mem_fn(放大器; MyClass的:: bIsMarkedToDelete)));
} 性病::法院LT&;&LT; 我=&LT;&LT; I&LT;&LT; values.size():&所述;&下; values.size()&所述;&下; \\ n;
性病::法院LT&;&LT; 我=&LT;&LT; I&LT;&LT; hashtable.size():&所述;&下; hashtable.size()&所述;&下; \\ n;
}
values.clear();
性病::法院LT&;&LT; 做的\\ n;
}
if I uncomment these
//BaseList baselist; //MemberList memberlist;
outside the loop and comment out the ones inside the loop it crashes. I need to be able to have the baselist (and memberlist) outside any loop. How is this achieved?
Edit
The actual problem I am trying to solve in it's simplest form is this.
I want to have a std::vector of
MyClass
, call it AllThingsBunchedTogether. I also want to have a std::vector ofBaseList
, call it AllThingsSpreadOut.So
- AllThingsBunchedTogether might contain (just the
anInt1
part for the sake of compactness):1,2,1,10,2,3,4,4,5,9,10,10
.- AllThingsSpreadOut might contain (zero not used for now) at [1]
1,1
at [2]2,2
at [3]3
at [4]4,4
at [5]5
at [9]9
at [10]10,10,10
.Note that the numbers themselves aren't be stored in the
BaseList
, but e.g., theMyClass
(1, "John").At [1] it could be "Mike", "John", at [2] it could be "Mike", "Dagobart" at [3] "John" ... at [10] "John" "Mike" "Dagobart" etc so that there no duplicates in any of the
BaseList
at AllThingsSpreadOut[i] since eachMyClass
in eachBaseList
hashes to a different value (anInt1 + Name
).In essence,
anInt1
tells where theMyClass
lives in AllThingsSpreadOut, butanInt1 + name
guarantees uniqueness within eachBaseList
.So the idea is that AllThingsSpreadOut is a vector of
BaseList
where at eachBaseList
at vector location is a list of similar things.Then, when I remove things from AllThingsBunchedTogether (not by a clear, but by a search to remove some items like in the code below IsMarkedToDelete), they will automatically disappear from the corresponding AllThingsSpreadOut.
AllThingsSpreadOut acts as a sort for AllThingsBunchedTogether, with intrusive semantics. AllThingsBunchedTogether allows superfast access through [].
End Edit
#include <vector> #include <iostream> #include <boost/intrusive/list.hpp> using namespace boost::intrusive; class MyClass : public list_base_hook<link_mode<auto_unlink>> // This is a derivation hook { public: std::string name; bool bIsMarkedToDelete; int anInt1; public: list_member_hook<link_mode<auto_unlink>> member_hook_; // This is a member hook MyClass(std::string n, int i) : name(n), anInt1(i), bIsMarkedToDelete(false) {} }; bool IsMarkedToDelete(const MyClass &o) { return o.bIsMarkedToDelete; } //Define a list that will store MyClass using the public base hook typedef list<MyClass, constant_time_size<false>> BaseList; // Define a list that will store MyClass using the public member hook typedef list<MyClass, member_hook<MyClass, list_member_hook<link_mode<auto_unlink>>, &MyClass::member_hook_>, constant_time_size<false> > MemberList; int main() { bool done = false; std::vector<MyClass> values; std::string names[] = {"John", "Mike", "Dagobart"}; //BaseList baselist; //MemberList memberlist; int i = 0; while(!done) { // Create several MyClass objects, each one with a different value for (int j = 0; j < 11; ++j) values.emplace_back(names[j % 3], j); BaseList baselist; MemberList memberlist; // Now insert them in t-he reverse order in the base hook list for (auto& e : values) { baselist.push_front(e); memberlist.push_back(e); } // Now test lists auto rbit(baselist.rbegin()); auto mit(memberlist.begin()); auto it(values.begin()), itend(values.end()); // Test the objects inserted in the base hook list for (; it != itend; ++it, ++rbit) { if (&*rbit != &*it) return 1; } // Test the objects inserted in the member hook list for (it = values.begin(); it != itend; ++it, ++mit) { if (&*mit != &*it) return 1; } # if 0 for(auto& e : values) std::cout << e.anInt1 << "\n"; for(auto& e : baselist) std::cout << e.anInt1 << "\n"; for(auto& e : memberlist) std::cout << e.anInt1 << "\n"; #endif // 0 if(2 == i) { for(auto& e: values) std::cout << e.name << "\n"; for(auto& e: values) { if("Mike" == e.name) e.bIsMarkedToDelete = true; } values.erase( std::remove_if(values.begin(), values.end(), IsMarkedToDelete), values.end()); } if(i++ > 3) { values.clear(); done = true; } std::cout << "\n"; std::cout << values.size() << "\n"; std::cout << baselist.size() << "\n"; std::cout << memberlist.size() << "\n"; } }
解决方案I've seen it late, but anyways, here goes:
What you describe matches exactly the implementation of an intrusive hash table of
MyClass
elements, where
anInt1
is the hash (the bucket identifier) for an element- the bucket lists are implemented as linked lists
equality is defined as equality of
(anInt1, Name)
So really, your program could just be:std::unordered_set<MyClass> values { { "John", 0 }, { "Mike", 1 }, { "Dagobart", 2 }, { "John", 3 }, { "Mike", 4 }, { "Dagobart", 5 }, { "John", 6 }, { "Mike", 7 }, { "Dagobart", 8 }, { "John", 9 }, { "Mike", 10 }, }; for(int i = 0; i<=3; ++i) { if(2 == i) { for(auto& e: values) std::cout << e.name << " "; std::cout << "\n"; for(auto& e: values) e.bIsMarkedToDelete |= ("Mike" == e.name); for(auto it=begin(values); it!=end(values);) { if (it->bIsMarkedToDelete) it = values.erase(it); else ++it; } } std::cout << "i=" << i << ", values.size(): " << values.size() << "\n"; } values.clear(); std::cout << "Done\n";
if you really wanted contiguous storage, I can only assume you wanted this for performance
you do not want to use pointers instead of objects, since that simply negates the memory layout ("AllThingsBunchedTogether") benefits and you'd be better of with the
unordered_set
orunodered_map
as aboveyou do not want to use
auto_unlink
mode, since it cripples performance (by doing uncontrolled deletion triggers, by inhibiting constant-timesize()
and by creating thread safety issues)instead, you should employ the above stratagy, but with
boost::intrusive::unordered_set
instead see http://www.boost.org/doc/libs/1_57_0/doc/html/intrusive/unordered_set_unordered_multiset.htmlHere, again, is a proof-of-concept:
#include <vector> #include <iostream> #include <boost/intrusive/unordered_set.hpp> #include <vector> //#include <functional> //#include <algorithm> namespace bic = boost::intrusive; struct MyClass : bic::unordered_set_base_hook<bic::link_mode<bic::auto_unlink>> { std::string name; int anInt1; mutable bool bIsMarkedToDelete; MyClass(std::string name, int i) : name(name), anInt1(i), bIsMarkedToDelete(false) {} bool operator==(MyClass const& o) const { return anInt1 == o.anInt1 && name == o.name; } struct hasher { size_t operator()(MyClass const& o) const { return o.anInt1; } }; }; typedef bic::unordered_set<MyClass, bic::hash<MyClass::hasher>, bic::constant_time_size<false> > HashTable; int main() { std::vector<MyClass> values { MyClass { "John", 0 }, MyClass { "Mike", 1 }, MyClass { "Dagobart", 2 }, MyClass { "John", 3 }, MyClass { "Mike", 4 }, MyClass { "Dagobart", 5 }, MyClass { "John", 6 }, MyClass { "Mike", 7 }, MyClass { "Dagobart", 8 }, MyClass { "John", 9 }, MyClass { "Mike", 10 }, }; HashTable::bucket_type buckets[100]; HashTable hashtable(values.begin(), values.end(), HashTable::bucket_traits(buckets, 100)); for(int i = 0; i<=3; ++i) { if(2 == i) { for(auto& e: values) std::cout << e.name << " "; std::cout << "\n"; for(auto& e: values) e.bIsMarkedToDelete |= ("Mike" == e.name); values.erase(std::remove_if(begin(values), end(values), std::mem_fn(&MyClass::bIsMarkedToDelete))); } std::cout << "i=" << i << ", values.size(): " << values.size() << "\n"; std::cout << "i=" << i << ", hashtable.size(): " << hashtable.size() << "\n"; } values.clear(); std::cout << "Done\n"; }
这篇关于努力学习的boost ::侵入Q2的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!