【问题标题】:Call to implicitly-deleted default constructor of 'unordered_set< vector<int> >'调用 'unordered_set<vector<int>>' 的隐式删除的默认构造函数
【发布时间】:2020-11-02 06:40:20
【问题描述】:

似乎当我尝试定义一个 unordered_set 向量时,我收到一条错误消息:“调用 unordered_set&lt; vector&lt;int&gt; &gt; 的隐式删除的默认构造函数。”当我定义一个常规(有序)集时,这不会发生:set&lt; vector&lt;int&gt; &gt;。看来我需要定义hash&lt;vector&lt;int&gt;&gt; 才能消除错误。

有谁知道为什么我只有在使用unordered_set 时才会收到此错误?两种数据结构都不应该使用散列,那么为什么 unordered_set 需要自定义的散列函数呢?事实上,一个常规的(有序的)set 不应该也需要一些自定义的比较器来订购vector&lt;int&gt; 数据结构吗?

【问题讨论】:

  • std::vector 已经有一个重载的operator &lt;。这就是它与 std::set 一起使用的原因。
  • std::set 不使用散列。

标签: c++ hash set unordered-set


【解决方案1】:

这是因为 unordered_set 使用 std::hash 模板来计算其条目的哈希值,并且没有 std::hash 对。您必须定义自定义哈希才能使用 unordered_set。

    struct vector_hash
{
    template <class T1, class T2>
    std::size_t operator () (std::pair<T1, T2> const &v) const
    {
        return std::hash<T1>()(v.size());    
    }
};

然后将你的 unordered_set 声明为 -

std::unordered_set< vector<int>, vector_hash> set;

这个哈希函数不好。这只是一个例子。

【讨论】:

  • 为什么vector&lt;int&gt;unordered_set 需要pair 的哈希函数? vector&lt;int&gt; 不需要哈希函数吗?
【解决方案2】:

两种数据结构不应该都使用散列

没有。这是记录在案的,您可以随时自行查找:

  • std::set

    std::set 是一个关联容器,其中包含一组已排序的 Key 类型的唯一对象。排序是使用键比较函数Compare 完成的。搜索、删除和插入操作具有对数复杂性。集合通常实现为红黑树

    注意Compare 默认为std::less&lt;Key&gt;std::vector 重载operator&lt;

  • std::unordered_set,用于比较

    无序集是一个关联容器,其中包含一组 Key 类型的唯一对象。搜索、插入和删除具有平均恒定时间复杂度。

    在内部,元素没有按任何特定顺序排序,而是组织成桶。元素放入哪个桶完全取决于其值的哈希

    并且哈希类型参数默认为std::hash&lt;Key&gt;。这有一个标准库类型的特化列表,std::vector 不包括在该列表中。

【讨论】:

    【解决方案3】:

    很遗憾,std::hash 没有针对 std::vector 的一般特化。 std::vector&lt;bool&gt;只有一个特化,用处不大:

    int main()
    {
        std::hash<std::vector<bool>> hash_bool;  // ok
        std::hash<std::vector<int>> hash_int;  // error
    }
    

    Demo.

    恕我直言,原因是没有标准的方法来组合散列。因为您必须组合所有元素的散列才能构造整个向量的散列。但是为什么没有标准的方法来组合哈希 - 这是个谜。

    您可以改用boost::hashabsl::Hash,例如:

    unordered_set<vector<int>, boost::hash<vector<int>>>
    

    请注意,absl::Hash 计算的哈希码不能保证在程序的不同运行中保持稳定。这可能是一个好处(如果您的目标是安全),也可能是一个缺点(如果您的目标是可重复性)。

    【讨论】:

      【解决方案4】:

      set 使用自平衡树,而 unordered_set 使用纯散列。

      【讨论】:

        猜你喜欢
        • 2016-09-11
        • 2022-01-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-09-10
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多