【问题标题】:C++ STD Unordered Set/Map vs Boost Unordered Set/MapC++ STD 无序集/映射与提升无序集/映射
【发布时间】:2022-01-23 06:25:59
【问题描述】:

它们之间有什么区别,你应该在什么时候使用它们?

我在一台旧笔记本电脑上进行了一些测试,在存储 int 和 long 等基本类型时似乎没有显着的性能差异。我认为主要区别之一是 boost container emplace 方法不支持 std::piecewise_construct 和元组,这会导致额外的开销。

编辑:我正在研究的东西已经有很多提升功能,所以我不担心提升库的兼容性问题。

【问题讨论】:

  • c++的基本取自boost,而且比较新,所以C++的一般比较好。但是其他的也可以。

标签: c++ boost hash stl set


【解决方案1】:

Boost 具有一些标准库中不存在的功能。在我脑海中浮现:

  • Boost Hash,它比专门化 std::hash<> 更灵活、更容易定制(尽管也支持专门化 boost::hash<>;更简单的方法是实现一个 inline friend size_t hash_value(T const&),它会“神奇地”被默认选中hash<> 实现

  • Boost 倾向于更好地支持异构查找(查找扩展的查找/插入签名)

  • 有序版本可能有额外的构造函数来有效地构建已知有序序列

  • 一般而言,Boost 容器(包括 Boost Container 库中的其他容器)具有更多保证/选项:

    • (更好)支持有状态分配器(包括 scoped_allocator_adaptor,因此完全支持uses_allocator/allocator_arg_t
    • 构造函数不分配
    • 对模板参数中不完整类型的一些支持
  • 据我所知,分段构造在 Boost 中非常好。例如。 1.48.0 的更改说明列表:

    * `emplace` used to emulate the variadic pair constructors that
      appeared in early C++0x drafts. Since they were removed it no
      longer does so. It does emulate the new `piecewise_construct`
      pair constructors - only you need to use
      `boost::piecewise_construct`. To use the old emulation of
      the variadic constructors define
    

总结

我预计性能不会有显着差异。

将存在实施质量差异。 Boost 的编译和支持较旧的编译器版本可能会慢一些。

奖金

作为对 cme​​ts 的回复,这里有一个示例,概述了上面提到的一些功能,特别是分段放置的使用:

Live On Compiler Explorer

#include <boost/unordered_map.hpp>
#include <iomanip>
#include <fmt/ranges.h>
#include <fmt/ostream.h>

struct MyKey {
    MyKey(int i, std::string s) : _i(i), _s(std::move(s)) {}

    bool operator==(MyKey const&) const = default;

  private:
    int _i;
    std::string _s;

    friend size_t hash_value(MyKey const& mk) {
        using boost::hash_value;
        size_t seed = hash_value(mk._i);
        boost::hash_combine(seed, hash_value(mk._s));
        return seed;
    }

    friend auto& operator<<(auto& os, MyKey const& mk) {
        return os << "[" << mk._i << ", " << std::quoted(mk._s) << "]";
    }
};

int main() {
    boost::unordered_map<MyKey, std::string> m;

    m.emplace(boost::unordered::piecewise_construct,
              boost::make_tuple(42, "forty-two"),
              boost::make_tuple("the answer"));

    m.emplace(std::piecewise_construct,
              std::/*make_*/tuple(43, "forty-three"),
              std::/*make_*/tuple("not the answer"));

    fmt::print("m: {}\n", m);
}

打印

m: {([43, "forty-three"], "not the answer"), ([42, "forty-two"], "the answer")}

【讨论】:

  • 我从未见过 boost::piecewise_construct。使用 piecewise_construct 和 tuples 进行 boosting 的语法是什么?
  • 我可以试试看...
  • 在答案中添加了一个示例并 Live On Compiler Explorer
  • 语法太难了。当我用 std::piecewise_construct 和 std 元组尝试不同的东西时,我遇到了大量不可读的编译器错误。我正在尝试 m.emplace(std::piecewise_construct, std::make_tuple(...)) 和 m.emplace(std::piecewise_construct, std::forward_as_tuple(...))
  • 这些都适用于集合,但实际上,不需要分段(因为没有“片段”):godbolt.org/z/9E8ncor4s
猜你喜欢
  • 2010-10-27
  • 1970-01-01
  • 1970-01-01
  • 2017-05-26
  • 2013-08-02
  • 2019-03-27
  • 1970-01-01
  • 2011-11-19
  • 2020-11-17
相关资源
最近更新 更多