C++: 使用异构查找来提高性能

编程语言及工具

105人已加入

描述

关联容器将元素与键相关联。插入或从容器中查找元素需要等效键。通常,容器要求键是特定类型的,这会导致调用站点的效率低下,需要在接近等效的类型(如 std::string 和 absl::string_view)之间进行转换。

C++

为了避免这种不必要的工作,一些容器提供了异构查找。此功能允许调用者传递任何类型的键(只要用户指定的比较器函子支持它们)。有关 STL 容器中此功能的示例,请参见 std::find。

使用异构查找来提高性能

使用异构查找的一个常见原因是性能。我们可以构造 key_type,但这样做需要我们宁愿避免的非平凡工作。例如:

std::map m = ...;
absl::string_view some_key = ...;
// Construct a temporary `std::string` to do the query.
// The allocation + copy + deallocation might dominate the find() call.
auto it = m.find(std::string(some_key));

Instead, we can use a transparent comparator like so:

struct StringCmp {
  using is_transparent = void;
  bool operator()(absl::string_view a, absl::string_view b) const {
    return a < b;
  }
};


std::map m = ...;
absl::string_view some_key = ...;
// The comparator `StringCmp` will accept any type that is implicitly
// convertible to `absl::string_view` and says so by declaring the
// `is_transparent` tag.
// We can pass `some_key` to `find()` without converting it first to
// `std::string`. In this case, that avoids the unnecessary memory allocation
// required to construct the `std::string` instance.
auto it = m.find(some_key);

STL 容器支持和替代方案

有序容器 (std::{map,set,multimap,multiset}) 从 C++14 开始支持异构查找。从 C++17 开始,无序容器仍然不支持它。有添加此功能的建议,但尚未被接受。

GTL 容器支持

在 gtl/absl 中支持异构查找的容器包括:

go/btree:btree 容器 absl::btree_{set,map,multiset,multimap}。它们隐含地支持对具有常见比较器的类字符串键的异构查找,例如 std::less 其中 T 是 {std::string, absl::string_view, absl::Cord} 之一(对于 std::greater )。所有其他密钥类型都需要用户明确选择加入。

go/swisstable:无序容器 absl::{flat,node}_hash_{set,map}。它们要求哈希函数和相等函数都被标记为透明的。出于性能原因,swisstable 隐式支持字符串键表的异构查找。所有其他密钥类型都需要用户明确选择加入。

扁平有序容器 gtl::flat_{set,map,multiset,multimap}。

gtl::LockFreeHash{Set,Map}。

本文那个题目的答案是 None of the above: this code is correct and efficient.

编辑:黄飞

 

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分