C++ STD 无序集/映射与 Boost 无序集/映射

dan*_*iii 3 c++ hash boost stl set

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

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

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

seh*_*ehe 6

Boost 有一些标准库中不存在的功能。我的头顶上浮现出:

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

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

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

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

    • (更好)支持有状态分配器(包括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
    
    Run Code Online (Sandbox Code Playgroud)

概括

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

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

奖金

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

实时编译器资源管理器

#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);
}
Run Code Online (Sandbox Code Playgroud)

印刷

m: {([43, "forty-three"], "not the answer"), ([42, "forty-two"], "the answer")}
Run Code Online (Sandbox Code Playgroud)