2016-10-17 45 views
2

我有下面的代碼片段C++設計問題與unordered_set和迭代

template <class T> 
inline void hash_combine(std::size_t & seed, const T & v) 
{ 
    std::hash<T> hasher; 
    seed ^= hasher(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2); 
} 

const size_t INF(numeric_limits<size_t>::max()); 

class nodehasher; 

class node{ 

public: 
    int x,y; 
    unordered_set<node, nodehasher>::iterator neighbs[6]; //Issue Here 
    node(){} 
    node(int x_, int y_):x(x_),y(y_){} 
    void set(int x_, int y_){x = x_,y = y_;} 
    bool operator == (const node &n)const{ 
    return x == n.x && y == n.y; 
    } 
}; 

class nodehasher{ 
    std::size_t operator()(node const& n) const{ 
    std::size_t seed = 0; 
    hash_combine(seed, n.x); 
    hash_combine(seed, n.y); 
    return seed; 
    } 
}; 

我似乎有聲明指向類節點內部節點本身的迭代器的問題。

這將導致太冗長的錯誤數量巨大。

現在我知道我可以讓我的neighbs數組,指針數組節點, 但我想避免指針的原因很明顯

我用這將是一個典型的簡化方式:

unordered_set<node, nodehasher> nodes; 
void typical_use(node dest){ 
    auto src_node = node(0,0); 
    int neighbcount = 0; 
    auto iter = dest.insert(node).first; 
    src_node.neighbs[neighb_count] = iter; 
} 

我能明顯將其轉化爲指針,並做到:

src_node.neighbs[neighb_count] = &(*iter); 

但有沒有辦法避免什麼我想要做的指針?

編輯:

由於許多意見和答案都指出這兩個指針和迭代的容器元素的翻版 後得到失效,從而是一個壞主意,將它們存儲。

我在想,如果工作方式如下節點的unordered_set的相反,我會用指針的節點的unordered_set,這樣

unordered_set<shared_ptr<node> > nodes; 

東西還有,如果我知道那個節點的數量始終是將小於500,我可以放棄這個整個散列表的想法,並使用一個數組,每次我將不得不搜索數組來檢查節點是否已經存在。

能否請你指出哪一種方法更好?

+0

我不知道這是否是一個成員變量智能存儲迭代器。我不知道在更改unordered_set後內部是否會發生內部變化,然後迭代器會指向其他內容或出現意想不到的情況。 – Hayt

+0

@Hayt哦,天哪,我甚至都沒有想過,看起來像指針,謝謝,我應該刪除這個問題嗎? –

+0

如果問題沒有爲您提供更多價值,您可以刪除它。您也可以嘗試將問題重新編輯/編輯到您想知道指針替代的位置,而不使用迭代器數組部分。 – Hayt

回答

2

標準集裝箱需要完整的類型值。 node在您使用它實例化unordered_set<node, nodehasher>時不是完整類型。

您可以使用Boost.Container,因爲它們允許不完整的類型,但我沒有看到散列容器(因此您必須使用set)。

但是,您應該小心存儲迭代器,因爲至少對於來自標準庫的​​容器,它們可能會在 重新哈希時失效。引用(和指針)不會失效。

+0

我可以使用智能指針來達到這個目的嗎?是否有適合此目的的智能指針? –

+0

你可以,但它很容易結束循環依賴。如果你把你的指針當作只有觀察者的指針,那麼你應該很好地使用它們,特別是因爲所有的節點都屬於容器,所以它們的生命週期是衆所周知的。 – krzaq