其他分享
首页 > 其他分享> > c-使用智能指针在大型对象集合中创建多个索引

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