在 shared_ptr 的 unordered_set 中查找值
Find a value in an unordered_set of shared_ptr
我想在 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
进行比较桶内)。只需为您的容器指定它们。
#2 的示例代码:
#include <cassert>
#include <memory>
#include <unordered_set>
struct 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());
}
根据here:
Note that the comparison operators for shared_ptr simply compare pointer values; the actual objects pointed to are not compared.
所以只有当 shared_ptr
指向同一个对象时 found
才为真:
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
我想在 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
进行比较桶内)。只需为您的容器指定它们。
#2 的示例代码:
#include <cassert>
#include <memory>
#include <unordered_set>
struct 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());
}
根据here:
Note that the comparison operators for shared_ptr simply compare pointer values; the actual objects pointed to are not compared.
所以只有当 shared_ptr
指向同一个对象时 found
才为真:
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