在shared_ptr的unordered_set中查找一个值

问题描述 投票:0回答:2

我想在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);
    }
  };
}

知道如何让它发挥作用吗?

c++ shared-ptr unordered-set
2个回答
11
投票

您存储了一个指向整数的指针。当您查找集合中的项目时,您不是在比较(指向的)整数,而是在比较指针本身。

当您将 new 指针分配给 new 整数对象进行搜索时,它不会比较相等,因为它是不同的整数对象(即使它存储相同的值)。

您的选择是:

  1. 不要存储指向集合中整数的指针,只需直接存储整数。

    那么,你的键是

    42
    ,搜索
    42
    就会找到它,因为整数是按值进行比较的

  2. 存储指针并使用自定义哈希和比较器来比较指向的整数而不是指针。

    您不应该(尝试)用哈希专业化污染

    std
    命名空间,而且无论如何这还不够(哈希用于存储桶查找,但键仍与存储桶内的
    KeyEqual
    进行比较)。只需为您的容器指定它们

#2 的示例代码:

#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()); }
    

1
投票
根据

这里

请注意,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
    
© www.soinside.com 2019 - 2024. All rights reserved.