我在一个库中工作,其中一些无关紧要的元素必须用名称标识(即值与名称相关联)。名称是用户的字符串,无论其内部表示是什么,并且应该透明地行为。
考虑到频繁的查找会发生,我考虑过使用无序的地图。
无序关联容器通过数字(通常为std::size_t
类型)存储其元素,无论其类型是什么,这些数字是使用散列函数获得的。这意味着:
我考虑过两种解决方案。
使用数据本身来计算哈希值。考虑:
constexpr
哈希函数(constexpr
本身)以及存储在类本身中的哈希值,以便以后快速检索(通过hasher对象)。Boost.Log库,如here所述,维护一个全局(即静态)表,该表将名称与其哈希值相关联。可能的实现如下:
考虑:
std::map
好多了,是吗?std::map
会更好吗?注意:即使我可以访问gcc和clang提供的实验性支持,我还没有添加c++14
标记。请不要犹豫,使用即将出版的规范中包含的功能。
答案 0 :(得分:2)
在这些条件下使用无序地图是否正确?会吗 最好是使用std :: map吗?
如果您不需要订购条目,使用unordered_map
通常比map
更有效。由于两者都具有几乎相同的界面,当然这很容易衡量(你应该这样做)。
如果1为'是',则采用哪种方法 更好,为什么?在Boost.Log中使用的那个看起来真的很无效, 为什么它被用来代替我解释的另一个,即使字符串是 在编译时不一定知道吗?
您应该更好地阅读Boost文档。我没有读到关于线性复杂性查找的任何内容。 attribute_set
的描述建议使用关联容器(我希望std :: unordered_map,但您可以自己检查源代码)。文档中还清楚地提到了使用标识符而不是字符串的原因:
“使用标识符比使用字符串更有效。例如,复制不涉及动态内存分配,比较运算符非常轻量级。”
这对您的案例是否有益取决于您使用这些数据结构的方式。由于您指示字符串标识符可以表示为字符串文字(但考虑您是否需要翻译这些字符串),您只需要传递一个指针来复制字符串标识符。但是,比较仍然比boost::attribute_name
s慢。
答案 1 :(得分:0)
在这些条件下使用无序地图是否正确?会吗 最好使用
std::map
代替吗?
虽然可能值的数量大于散列值的类型可能会发生冲突,但是当它们发生冲突时,容器会注意到散列值中已经存在一个guest虚拟机,并直接比较键。因此,不同的键永远不会发生碰撞。尝试使用始终返回固定值的哈希函数,并查看插入键时会发生什么 - 它将变为慢,这就是哈希算法很重要的原因。
因此,如果您提及频繁查找,并且不需要订单,则使用std::unordered_map
是一个不错的选择。不过,正如D Drmmr建议的那样,你仍然应该对std::map
进行衡量。
如果1为'是',哪种方法更好,为什么?使用的那个 Boost.Log看起来真的很无效,为什么用它而不是 其他我解释过,即使字符串不一定是已知的 编译时?
如果您因为哈希值相等而担心不同的密钥冲突,那么请不要担心;如上所述,这不是问题。因此,您应该选择第一种方法,因为它允许编译时散列,并且不会遇到第二种方法的所有问题。
可能的实施:
// You stated that names were constant and constructed from string literals.
// Borrowed from the example at http://en.cppreference.com/w/cpp/language/constexpr
class
name final
{
private:
const char * const
s; // string
const std::size_t
l; // length
public:
template<std::size_t N> constexpr
name
( const char (& s)[N] )
noexcept
: s( s ) , l( N-1 )
{ }
// Interface that enables hashing algorithms to operate on your class.
// If hashing is to happen at compile-time, the methods must be
// declared `constexpr`.
};
struct
hasher final
{
constexpr std::size_t
operator()
( const name & n )
const noexcept
{
return 0; // read below
}
};
您必须实现哈希算法的接口才能访问name
类下面的数据。此外,如示例中所述,方法应为constexpr
- 声明;否则,无法从constexpr
启用的散列函数调用它们。至于散列算法,有很多,在某些情况下都适用。 This page详细阐述了该主题,并介绍了X65599的实现,但不使用constexpr
。您可以先尝试一下,然后检查它在您的情况下的表现。