当键是对象的一部分时最合适的关联 STL 容器 [C++]
我有一个这样的类:
struct Thing
{
unsigned index;
// more data members
};
我使用 std::map
来包含我的 Thing
。调用代码看起来像这样:
Thing myThing(/*...*/);
std::map<Thing> things;
things[myThing.index] = myThing;
// ...
Thing &thing3 = things[3];
我想知道是否有一种方法可以直接使用 Thing::index
而无需隐式地将其复制到 pair::first
中。
我想我需要提供某种 Thing
比较运算符,但这没关系。 std::set
可能有效,但我需要整个 Thing
对象作为键:
std::set<Thing> things;
Thing &thing3 = *things.find(Thing(3));
除了将 Thing
重构为 std: :pair
,我可以用STL做得更好吗?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
我不明白为什么
不完全按照你的意愿去做。没有索引字段的重复/复制,并且键比较与映射方法一样高效;有什么理由不喜欢呢?
根据下面的评论更新:
如果 Thing 太重量级以至于您不想复制它,那么您最终可能会得到更像这样的代码:
虽然恕我直言,重写指针值比较是相当邪恶的最好采用更详细的方式,将显式“比较”参数设置为模板参数。
需要记住的一件事(根据我自己对重量级对象的大优先级队列的经验):基于
std::pair> 的容器可能比基于
std::pair>
的容器具有显着的优势std::pair
因为前者的遍历仅触及键(例如find
)与后者相比可以更加提高缓存效率,这也会将大量不需要/不相关的heavyweight_object
字节提取到缓存中(当然取决于细节和数量,但事实上,这种效果很容易完全淹没复制密钥的相对较小的成本)。I don't see why
doesn't do exactly what you want. No duplication/copying of the index field, and key comparison as efficient as the map approach; what's not to like ?
Update in light of comments below:
If Thing is so heavyweight that you don't want to copy it, then you'd probably end up with code more like:
although IMHO overriding pointer value comparison is fairly evil and it'd be better to go the more verbose route of an explicit "Compare" argument to the set template args.
One thing to bear in mind (from my own experience of big priority queues of heavyweight objects): there may be significant advantages to
std::pair<trivial_key,shared_ptr<heavyweight_object>>
-based containers overstd::pair<trivial_key,heavyweight_object>
due to the fact that traversals of the former touching only keys (e.gfind
) can be much more cache efficient compared with the latter which will also fetch a lot of mostly unneeded/irrelevantheavyweight_object
bytes into cache (depends on the details and numbers of course, but in fact this effect could easily completely swamp the relatively minor cost of duplicating the key).使用私有继承或组合包装映射,重新导出访问器并根据所需功能实现插入。我建议在 key getter 上对你的新类型进行patametrize - 一个函子,它返回给定存储类型对象的键。
Wrap map with private inheritance or composition, reexport accessors and implement insertion in terms of required functionality. I'd recommend to patametrize your new type on key getter - a functor that returns a key given an object of storage type.
我记得 boost::flyweight支持 密钥提取器以避免在可以轻松从对象中获取密钥时为密钥保留额外的存储空间。
我并不建议在
map
或unordered_map
足够的所有情况下使用 Flyweight,我很难相信这些类不支持类似的密钥提取模式,虽然我在文档或谷歌中找不到任何提及。无论哪种情况,这都可能对您有帮助I Recall that boost::flyweight supports key extractors to avoid keeping extra storage for the key, when it is readily obtainable from the object.
I'm not suggesting to use flyweight in all cases where
map
orunordered_map
are sufficient, I have a hard time believing those classes won't support a similar key extraction pattern, although i can't find any mention in the docs or google. In either case this might be helpful to you使用对象的内存地址作为映射中的键怎么样?
因此,您不需要将密钥存储在对象中,我认为这是一个坏主意,因为密钥与对象状态没有任何关系。
What about using the memory address of your object as a key in your map??
So you don't need to store the key in your object which I think is a bad idea because the key does not has any relation with the objects state.