我想在unordered_set中找到一个值,但失败了:
typedef std::shared_ptr<int> IntPtr;
std::unordered_set<IntPtr> s;
s.insert(std::make_shared<int>(42));
bool found = s.find(std::make_shared<int>(42)) != s.end();
cout<<std::boolalpha<<found<<endl; // false
已尝试关注但仍然无效。
namespace std {
template <> struct hash<IntPtr> {
size_t operator()(const IntPtr& x) const noexcept {
return std::hash<int>()(*x);
}
};
}
知道如何让它发挥作用吗?
您存储了一个指向整数的指针。当您查找集合中的项目时,您不是在比较(指向的)整数,而是在比较指针本身。
当您将 new 指针分配给 new 整数对象进行搜索时,它不会比较相等,因为它是不同的整数对象(即使它存储相同的值)。
您的选择是:
不要存储指向集合中整数的指针,只需直接存储整数。
那么,你的键是
42
,搜索42
就会找到它,因为整数是按值进行比较的
存储指针并使用自定义哈希和比较器来比较指向的整数而不是指针。
您不应该(尝试)用哈希专业化污染
std
命名空间,而且无论如何这还不够(哈希用于存储桶查找,但键仍与存储桶内的 KeyEqual
进行比较)。只需为您的容器指定它们。
#include <cassert>
#include <memory>
#include <unordered_set>
namespace Deref {
struct Hash {
template <typename T>
std::size_t operator() (std::shared_ptr<T> const &p) const {
return std::hash<T>()(*p);
}
};
struct Compare {
template <typename T>
size_t operator() (std::shared_ptr<T> const &a,
std::shared_ptr<T> const &b) const {
return *a == *b;
}
};
}
int main() {
std::unordered_set<std::shared_ptr<int>> sp;
auto p = std::make_shared<int>(42);
sp.insert(p);
assert(sp.find(p) != sp.end()); // same pointer works
assert(sp.find(std::make_shared<int>(42)) == sp.end()); // same value doesn't
// with the correct hash & key comparison, both work
std::unordered_set<std::shared_ptr<int>, Deref::Hash, Deref::Compare> spd;
spd.insert(p);
assert(spd.find(p) != spd.end());
assert(spd.find(std::make_shared<int>(42)) != spd.end());
}
这里:
请注意,shared_ptr 的比较运算符只是比较指针值;不比较所指向的实际对象。因此,仅当
found
指向同一个对象时,
shared_ptr
才会为真:
typedef std::shared_ptr<int> IntPtr;
std::unordered_set<IntPtr> s;
IntPtr p = std::make_shared<int>(42);
s.insert(p);
bool found = s.find(p) != s.end();
cout<<std::boolalpha<<found<<endl; // true