gpt4 book ai didi

c++ - 使用智能指针为大量对象创建多个索引

转载 作者:行者123 更新时间:2023-11-28 02:27:13 24 4
gpt4 key购买 nike

我正在为大量对象创建多个索引(即使用不同的键)。对象可以改变,集合可以缩小和增长。到目前为止我的想法:

保存指向对象的某种指针的多个集合。使用 set 而不是 map 以获得更好的封装。使用 unordered_set 可以很好地扩展大型数据集。理想情况下,这些指针都应该是某种形式的智能指针。

我可以很容易地从 unique_ptr 的主集合开始,它管理所有分配,以及使用“原始”指针的二级索引(我暂时不考虑支持函数,但请注意索引是一个multiset 作为它的键在整个集合中不会是唯一的):

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);

我正在考虑付出额外的努力,用对 master 集合的 unique_ptr 的 const 引用替换索引对原始指针的使用。我不确定我能不能,至少不容易。我想我会问是否有其他人已经走过那条路,或者有其他建议。

更新

到目前为止的经验教训:

  1. 数据存储类很酷
  2. reference_wrappers 很酷
  3. 具有“关键”对象数据存储成员 var 的 xx_set 比 xx_map 更节省空间。但是......你不能轻易地将 unique_ptr 用作 c++11 中的键。 c++14 显然可能通过 std::set<Key>::find 具有更好的设置功能.参见 here更多细节。因此,就目前而言,管理原始分配的数据存储在这里似乎比尝试强制使用 unique_ptr 作为设置键或使用映射增加键空间存储更有意义。
  4. 记住在对象的生命周期内强制键值为常量(使用构造函数中提供的常量值)

最佳答案

这是一种方法。

std::vector<unique_ptr>保存数据项(以确保地址在 vector 调整大小时不会更改),然后容器保存 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++ - 使用智能指针为大量对象创建多个索引,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30132951/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com