在std :: map的值上使用非ptr是一种很好的做法

时间:2015-09-02 00:48:39

标签: c++ stl

我想定义一个类似的地图    std::unordered_map<int, std::unordered_set<int>> 要么    std::unordered_map<int, std::unique_ptr<std::unordered_set<int>>>

我不确定哪一个更好。

我看不出第一个是否有任何问题。就Does std::map::iterator return a copy of value or a value itself?而言 第一个是安全的,因为每组地图的访问权也应该是参考类型。

如果是这样,哪一个更好?

3 个答案:

答案 0 :(得分:1)

我更喜欢std::unordered_map<int, std::unordered_set<int>>。大多数C ++容器由一种“头”数据结构组成,包含指向实际数据的指针(例如,std :: vector只是一个包含指向实际底层'数组'数据的指针的类)。这个'header'数据结构通常相对较小,所以如果你要存储std::unique_ptr,内存分配的实际开销(CPU时间开销和内存开销)都会相对较大。

另一方面,如果您的问题需要您有效地看到std::unordered_map中的条目为“空”,并且/或者您将在地图中包含大量这些空条目,请使用{{ 1}}可能更有效率。

另请注意,std::unique_ptrstd::set等容器的内存开销相对较大。如果该集合仅包含少量元素,请考虑使用std::map而不是std:vector。循环使用小向量来检查重复项可能比使用std::set的散列逻辑更有效(因为std::set的内存局部性将更有效地使用处理器内存缓存,请参阅演示文稿Chandler Carruth对CPPCON2014的评论,https://www.youtube.com/watch?v=fHNmRkzxHWs)。

答案 1 :(得分:0)

如果你想知道什么是最好的,你需要定义你的效用函数。

你在优化什么?问题就在于,我个人可以说,我更喜欢打字,所以std::unordered_map<int, std::unordered_set<int>>最好。但是,这可能不是你的效用函数。

如果您关注性能,那么如果使用std::unique_ptr,额外的间接级别将花费您,分配,跳和缓存加载。如果您在集合之间共享集合,那么std::shared_ptr将花费一跳但保持一致性并降低总体内存。

如果您的设置很小,经常是空的或经常更新,那么使用std::unordered_map<int,std::set<int>>

可能是有意义的

在某些用例中,您还可以组合地图和设置键,然后使用std::unordered_set<std::pair<int, int> >

如果支持,则std::tuple<int, int>

答案 2 :(得分:0)

std::unordered_map<int, std::unique_ptr<std::unordered_set<int>>> 这看起来很多余。 unique_ptr的全部意义在于,当它超出范围时 - 它会删除并破坏它指向的内容。
如果你的地图的值是一些需要删除的指针 - 继续。但你的价值是std::unordered_set即使没有指针也会被销毁和删除 因此,您基本上可以在智能指针上添加额外的创建和删除,而无需添加任何额外的功能。