如果我取消注释这些
//BaseList baselist;
//MemberList memberlist;
在循环之外并注释掉循环中的那些它崩溃了。我需要能够在任何循环之外使用baselist(和memberlist)。这是如何实现的?
修改
我想用它解决的实际问题是最简单的形式。
我希望有一个
MyClass
的std :: vector,称之为AllThingsBunchedTogether。 我还想要一个BaseList
的std :: vector,称之为AllThingsSpreadOut。所以
- AllThingsBunchedTogether可能包含(为了紧凑而只包含
anInt1
部分):1,2,1,10,2,3,4,4,5,9,10,10
。- AllThingsSpreadOut可能包含[1]
1,1
的[1]2,2
,[3]3
位于[4]4,4
at {4]5
at [5]9
位于[9]10,10,10
,位于[10]BaseList
。请注意,这些数字本身并不存储在
MyClass
中,而是存储在BaseList
(1," John")中。在[1]它可能是#34; Mike"," John",在[2]它可能是" Mike"," Dagobart&# 34;在[3] "约翰" ...在[10]" John" "麦克" " Dagobart"等等,以便没有重复 AllThingsSpreadOut [i]中的任何
MyClass
,因为每个BaseList
anInt1 + Name
哈希值为不同的值(anInt1
)。实质上,
MyClass
告诉anInt1 + name
在AllThingsSpreadOut中的位置,但BaseList
保证每个BaseList
内的唯一性。所以我的想法是AllThingsSpreadOut是
BaseList
的向量,其中向量位置的每个#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"; } }
都是类似事物的列表。然后,当我从AllThingsBunchedTogether中删除内容时(不是通过清除,而是通过搜索删除IsMarkedToDelete下面的代码中的某些项目),它们将自动从相应的AllThingsSpreadOut中消失。
AllThingsSpreadOut充当AllThingsBunchedTogether的排序,具有侵入性语义。 AllThingsBunchedTogether允许通过[]进行超高速访问。
结束修改
{{1}}
答案 0 :(得分:5)
我已经看到了很晚,但无论如何,这里是:
您所描述的内容与完全相同 MyClass
元素的侵入式哈希表的实现,其中
anInt1
是元素的哈希( bucket 标识符)将相等性定义为(anInt1, Name)
实际上,你的程序只是:
<强> Live On Coliru 强>
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";
如果你真的想要连续存储,我只能假设你想要这个性能
你不想要使用指针而不是对象,因为这只会消除内存布局(“AllThingsBunchedTogether”)的好处,你会更好地使用{{1} }或unordered_set
如上
您不想要使用unodered_map
模式,因为它会削弱性能(通过执行不受控制的删除触发器,禁止常量时间auto_unlink
并创建线程安全问题)
相反,您应该使用上述战略,但使用size()
代替http://www.boost.org/doc/libs/1_57_0/doc/html/intrusive/unordered_set_unordered_multiset.html
这里再次是一个概念验证:
<强> Live On Coliru 强>
boost::intrusive::unordered_set
答案 1 :(得分:0)
这是您忽略的错误消息:
Assertion `node_algorithms::inited(to_insert)' failed.
由此我们可以理解,元素被插入两次。这对于侵入式容器一般无效。
当你在循环中有你的列表时,它们每次都会被销毁并重新创建。但是当他们在外面时,你永远不会清除它们,而且你也永远不会清除values
,所以这个顺序发生了:
values
添加11个元素。values
添加到列表中。values
添加11个元素;它仍然有前11个所以现在有22个元素。values
添加到列表中。第一个崩溃,因为它已经在列表中。一种解决方案是在values.clear()
循环的顶部添加while(!done)
。