c-使用智能指针在大型对象集合中创建多个索引
作者:互联网
我正在将多个索引(即使用不同的键)创建到大量对象中.对象可以更改,并且集合可以缩小和增长.到目前为止,我的想法是:
保留指向对象的某种指针的多个集合.
使用set而不是map可以更好地封装.
使用unordered_set可以很好地处理大型数据集.
理想情况下,指针应全部为某种形式的智能指针.
我可以很轻松地从一个unique_ptrs的主集合开始,该主集合管理所有分配,以及使用“原始”指针的二级索引(我暂时省略了支持功能,但是请注意,索引是一个多集键在整个集合中不是唯一的):
typedef boost::unordered_set< boost::unique_ptr<MyObject>,myobject_hash,myobjects_equal > MyObjects;
typedef boost::unordered_multiset<const MyObject*,myobject_index2_hash,myobject_index2_equal > MyObjectsIndex2;
用法很简单:
MyObjects my_objects;
MyObjectsIndex2 my_objects_index2;
auto it_mo = my_objects.insert(
boost::unique_ptr<MyObject>(
new MyObject(...)
)
);
const MyObject* p_mo = it_mo.first->get();
my_objects_index2.insert(p_mo);
我正在考虑付出更多的努力,以对主集合的unique_ptrs的const引用替换索引对原始指针的使用.我不确定是否可以,至少不容易.我想问一下是否有人已经走过那条路,或者有其他建议.
UPDATE
到目前为止吸取的教训:
>数据存储类很酷
> reference_wrappers很酷
>具有“键”对象数据存储区成员var的xx_set比xx_map更节省空间.但是…在c 11中,您不能轻易使用unique_ptr作为键.显然,通过std :: set< Key> :: find,c 14可能具有更好的设置功能.有关更多详细信息,请参见here.因此,就目前而言,管理原始分配的数据存储似乎比尝试强制使用unique_ptr作为设置键或通过映射增加键空间存储更具意义.
>请记住在对象的生命周期内强制将键值设置为const(使用构造函数中提供的const值)
解决方法:
这是一种方法.
的std ::矢量<&的unique_ptr GT;来保存数据项(以确保在矢量调整大小时地址不发生变化),然后使用包含reference_wrappers(可复制引用)的容器进行索引. 编译示例:
#include <map>
#include <vector>
#include <set>
#include <string>
#include <functional>
#include <memory>
#include <iostream>
struct Thing {
Thing(std::string name, int value)
: _name { std::move(name) }
, _value { value }
{}
const std::string& name() const {
return _name;
}
void write(std::ostream& os) const {
os << "{ " << _name << " : " << _value << " }";
}
private:
std::string _name;
int _value;
};
inline std::ostream& operator<<(std::ostream& os, const Thing& t) {
t.write(os);
return os;
}
struct multi_index
{
using multi_by_name_index = std::multimap<std::string, std::reference_wrapper<Thing>>;
void add_thing(std::string name, int value) {
// todo: checks to ensure that indexes won't be violated
// add a new thing to the main store
_main_store.emplace_back(new Thing{std::move(name), value});
// store a reference to it in each index
auto& new_thing = *(_main_store.back().get());
_name_index.emplace(new_thing.name(), new_thing);
}
using multi_by_name_range = std::pair<multi_by_name_index::const_iterator, multi_by_name_index::const_iterator>;
multi_by_name_range get_all_by_name(const std::string name) const
{
return _name_index.equal_range(name);
}
private:
std::vector<std::unique_ptr<Thing>> _main_store;
std::multimap<std::string, std::reference_wrapper<Thing>> _name_index;
};
using namespace std;
int main()
{
multi_index mi;
mi.add_thing("bob", 8);
mi.add_thing("ann", 4);
mi.add_thing("bob", 6);
auto range = mi.get_all_by_name("bob");
for( ; range.first != range.second ; ++range.first) {
cout << range.first->second << endl;
}
return 0;
}
预期输出:
{ bob : 8 }
{ bob : 6 }
标签:c,c11,c14 来源: https://codeday.me/bug/20191010/1883497.html