【问题标题】:Why does a unordered_set with a custom hash function and custom class need an initial number of buckets?为什么具有自定义哈希函数和自定义类的 unordered_set 需要初始数量的桶?
【发布时间】:2020-06-23 00:09:01
【问题描述】:

基本上我的问题是,为什么不能编译?

#include <iostream>
#include <vector>
#include <unordered_set>
using namespace std;


int main() {
    vector<int> v{1,2,3};
    auto hash_function=[](const vector<int>& v){
        size_t hash;
        for (int i = 0; i < v.size(); ++i) {
            hash+=v[i]+31*hash;
        }
        return hash;
        };

unordered_set<vector<int>, decltype(hash_function)> s(hash_function);
std::cout<<s.bucket_count();
std::cout<<"here";


}

但如果我将 unordered_set 行更改为此

unordered_set<vector<int>, decltype(hash_function)> s(10,hash_function);

会的。为什么需要初始桶数?使用 lambda 强制我添加初始存储桶计数似乎很奇怪,但使用仿函数则不会。请参阅此处的示例:C++ unordered_set of vectors 以证明仿函数版本不需要初始桶数。

【问题讨论】:

  • 我有点困惑。你想使用cplusplus.com/reference/unordered_set/unordered_set/… 的哪个构造函数?
  • 换句话说,如果标准选择支持参数的所有组合(默认/迭代器对/初始化器列表 * 可选计数/哈希/相等/分配),那将是 48 个构造函数(默认更少参数),并可能导致重载决议中不同函数对象之间的歧义。所以标准选择了限制构造函数的形式。
  • @L.F.这个评论很有意义。我一直想知道为什么这么多构造函数“失踪”,但看了你是对的,它会导致构造函数的数量迅速增加。

标签: c++ unordered-set


【解决方案1】:

顺便说一句,如果您可以访问 C++20,则可以为 lambda 执行 decltype 而无需构造一个,而让 std::unordered_set 默认构造它。

using hash_function = decltype([](const std::vector<int>& v) {
    size_t hash = 0;
    for (int i = 0; i < v.size(); ++i) {
        hash += v[i] + 31 * hash;
    }
    return hash;
});

std::unordered_set<std::vector<int>, hash_function> s();

【讨论】:

    【解决方案2】:

    那只是因为没有这样的构造函数。

    only unordered_set constructor that takes one parameter 是采用自定义分配器的实例,而不是自定义散列函数。

    附:您未能在自定义哈希函数中将 hash 初始化为 0。这带来了更高的风险of nasal demons。你应该解决这个问题。

    【讨论】:

      猜你喜欢
      • 2012-11-09
      • 2018-06-07
      • 2020-08-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-06-13
      • 2015-03-23
      • 2020-03-26
      相关资源
      最近更新 更多