在std::unordered_set中为自定义Position类型正确使用emplace函数的问题
在std::unordered_set中为自定义Position类型正确使用emplace函数的问题
嘿,我看你已经在为自定义Position类型适配std::unordered_set做准备了——写了operator==用于相等判断,还定义了Position_hash哈希器,这两步走对了就成功一半啦!不过你贴的代码里main函数的unordered_set定义没写完,我来帮你补全,再仔细讲讲怎么正确用emplace。
首先,先把代码补全到可运行的状态,顺便优化下细节:
#include <unordered_set> #include <iostream> // 用来验证插入结果 struct Position { int y; int x; // 建议显式加带参数的构造函数,让emplace的使用更直观高效 Position(int y_, int x_) : y(y_), x(x_) {} bool operator==(const Position& other) const { return this->x == other.x && this->y == other.y; } }; struct Position_hash { inline std::size_t operator()(const Position& v) const { // 你原来的简单哈希方式,小范围坐标完全够用 return v.y * 31 + v.x; // 如果坐标范围很大,怕哈希冲突的话,可以换这种组合哈希方式 // std::size_t h1 = std::hash<int>()(v.x); // std::size_t h2 = std::hash<int>()(v.y); // return h1 ^ (h2 << 1); } }; int main() { // 必须指定哈希器类型为Position_hash,不然unordered_set不知道怎么算哈希 std::unordered_set<Position, Position_hash> positions_set; // 重点:emplace的正确高效用法——直接传Position构造函数的参数,原地构造对象 // 这种方式比先构造临时Position再insert更省性能,少一次拷贝/移动 positions_set.emplace(1, 2); // 原地构造y=1、x=2的Position positions_set.emplace(3, 4); // 当然也可以传已构造的Position对象,但这样就没发挥emplace的优势了 positions_set.emplace(Position{5, 6}); // 验证插入是否成功 if (positions_set.count(Position{1, 2})) { std::cout << "坐标(1,2)已经在集合里啦\n"; } }
这里再划几个关键细节:
- 显式构造函数很实用:虽然编译器会给结构体生成默认构造,但加个
Position(int y_, int x_)的构造函数,能让你直接用emplace(1,2)这种简洁写法,完美发挥emplace原地构造的高效性。 - 哈希与相等判断要匹配:
unordered_set先靠哈希器分组,再用operator==确认元素是否真的相等,所以这两个函数的逻辑要一致——你现在的实现都是基于x和y,完全没问题。 - 哈希冲突的小优化:如果你的坐标范围很大,原来的简单哈希可能会有较多碰撞,换成标准库哈希组合的方式,能降低冲突概率,让集合的查找插入更高效。
要是你不想加显式构造函数,那emplace就只能传Position临时对象,比如positions_set.emplace(Position{1,2}),但这样和直接用insert差别不大,浪费了emplace的优势。
备注:内容来源于stack exchange,提问作者Awed2
相关产品推荐
相关产品推荐

