如何在以std::pair为键的std::map中无冗余拷贝查找值?
无冗余拷贝查找
std::map<std::pair<std::string, std::string>, some_type>的最优方案 要实现无字符串拷贝的查找,核心是利用C14引入的透明比较器结合C17的std::string_view,避免构造std::pair<std::string, std::string>时的字符串拷贝操作,具体步骤如下:
1. 调整map的比较器为透明类型
默认的std::map使用std::less<std::pair<std::string, std::string>>作为比较器,不支持跨类型的透明查找。我们需要显式指定比较器为std::less<>(即std::less<void>),它会自动推导比较操作的参数类型,无需严格匹配键类型:
#include <map> #include <string> #include <string_view> std::map<std::pair<std::string, std::string>, some_type, std::less<>> my_map;
2. 使用std::pair<std::string_view, std::string_view>作为查找参数
std::string_view是轻量级的字符串视图,仅持有原字符串的指针和长度,不会拷贝内容。构造该pair传入find即可实现无拷贝查找:
const std::string str1 = "key_part1"; const std::string str2 = "key_part2"; // 无拷贝查找,string_view直接引用str1、str2的内容 auto it = my_map.find(std::pair<std::string_view, std::string_view>{str1, str2}); if (it != my_map.end()) { // 找到对应值,进行操作 some_type& value = it->second; }
为什么其他方法不行?
std::make_pair(str1, str2):会构造std::pair<std::string, std::string>,必然触发两次字符串拷贝。std::make_pair(std::ref(str1), std::ref(str2)):std::ref返回的reference_wrapper会被隐式转换为std::string,依然会触发拷贝。std::make_pair(std::move(str1), std::move(str2)):仅适用于可移动的字符串,且移动后原字符串会处于有效但未定义的状态,不符合题目中“str1、str2为常量或不可移动”的前提。
版本兼容性说明
- 透明比较器
std::less<>需要C++14及以上版本支持。 std::string_view和字符串与string_view的跨类型比较需要C++17及以上版本支持。
如果受限于旧C++标准,无法使用string_view,唯一的替代方案是预先缓存常用的std::pair<std::string, std::string>键对象,复用它们进行查找以减少拷贝次数,但这本质上是妥协方案,无法完全避免拷贝。
内容的提问来源于stack exchange,提问作者Voivoid
相关产品推荐
相关产品推荐

