2015-09-16 47 views
2

的unordered_set的值,我想找到unordered_set的值,但沒有成功查找的shared_ptr

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

任何想法如何使其工作?

+0

你需要明白它的意思有兩個共享指針是「平等」。 –

+1

你不應該爲**你的**類型專門化'std :: hash' ... – Jarod42

+0

'shared_ptr'比較指針值的比較運算符;不會比較指向的實際對象。 – dasblinkenlight

回答

4

您將指針存儲爲整數。在查找集合中的項目時,您不會比較(指向的)整數,而是指針本身。

當您分配一個新指針爲尋找一個新整數對象,也不會比較相等,因爲它是一個不同的整數對象(即使它存儲的值相同)。

的選項有:

  1. 不存儲指向整數您的設置,只需直接存儲整數。

    那麼,你的關鍵是42,並搜索42會發現它,因爲整數按值進行比較

  2. 指針存儲和使用自定義哈希和比較的尖,在整數比較,而不是的指針。無論如何(散列用於存儲桶查找,但密鑰仍與存儲桶中的KeyEqual進行比較),您不應該(嘗試)用您的散列專門化污染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()); 
} 
1

根據here

注意,比較操作符的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