2013-08-25 122 views
0

我想在C++中實現一個A *搜索函數,並且我在優先級隊列中遇到了很多麻煩。從我可以在網上找到的例子來看,似乎只需要定義一個重載「()」的比較器類;但是,似乎Visual C++編譯器希望爲優先級隊列的元素定義賦值運算符「=」,否則會生成一條錯誤消息,說:Visual C++ 2012:爲什麼priority_queue需要重載賦值運算符?

錯誤C2582:'運算符='功能在'節點'中不可用

指向其源代碼中實現<algorithm>庫的行。

所以我開始爲'node'類寫一個重載的「=」操作,只是爲了發現「push」操作在某個時候做了一個分配,所以我最終得到了一個相同的'node'對象。

我在這裏錯過了什麼嗎?

下面是相關代碼

node.h

#include <string> 
#include <ostream> 
//node used in the A* search 
struct node{ 
public: 
    friend void operator<<(std::ostream& o,node& n); 
    node(std::string& s):msg(s),gScore(0),hScore(0),parent(nullptr){}; 
    int getHeuristics(node& n); 
    bool operator==(node n){return n.msg.compare(msg)?false:true;}; 
    node& operator=(node& n){msg = n.msg;gScore = n.gScore;hScore = n.hScore; return *this;}; 
    void setG(int g){gScore = g;} 
    int getG(void) {return gScore;} 
    int getH(void) {return hScore;} 
    int getOverall(void){return hScore + gScore;} 
    node* getParent(void){return parent;} 
    std::string& msg; 
private: 
    node* parent; 
    int gScore; 
    int hScore; 
}; 

WordLadder.c(它的一部分;而 「比較」 僅僅以某種方式的節點進行比較):

string apple("apple"); 
    string shite("shite"); 
    string germanApple("apfel"); 
    node germanNode(germanApple); 
    node a(apple); 
    node b(shite); 
    a.getHeuristics(germanNode); 
    b.getHeuristics(germanNode); 
    priority_queue<node,vector<node>,comparitor> p; 
    p.push(a); 
    //cout<<b; 
    p.push(b); 
    cout<<b; //prints "apple" 
+0

標準容器通過複製元素來工作,所以必須有一個「operator =」可用。我不知道編譯器爲什麼抱怨你的情況,除非它真的很聰明,並且推測你應該定義一個「operator =」,因爲指針成員「node * parent」。一般來說,當有指針成員時,默認的「operator =」在語義上是不正確的。 – zentrunix

+0

@JoséX。 msg是「節點」類的公共成員。你能否詳細說明標準容器如何通過複製元素來工作?這可能與爲什麼會發生這種情況有關:\我很好奇,因爲將它們推到別的東西上,如矢量,似乎根本沒有改變內容。 – user2531913

+0

當您執行「p.push(a)」時,將「a」的副本壓入容器,而不是「a」本身。此外,忘了「味精」,請參閱我上面的編輯。 – zentrunix

回答

3
std::string& msg; 

msg = n.msg; 

這就是你的問題。您需要std::string msg,副本,而不是參考。

+0

它的確解決了問題!你能否向我解釋一下在這個例子中發生了什麼使他們完全相同?謝謝。 – user2531913

+0

@ user2531913您不能分配給引用,而是分配給被引用的對象。因此,當您嘗試交換兩個對象時,最終會引用兩個引用兩個相同字符串的對象。您可以在調試器中觀看此過程。非常具有啓發性。通常,如果您計劃複製類對象,請避免引用成員。 –

+0

@ user2531913:指針和引用之間有兩個區別,1 /引用不能爲空,2 /引用總是指向同一個對象。(2)的結果是當你分配給一個引用時,它在事實上分配給被引用的對象。爲避免無意中在腳下自己射擊,如果成員是引用,編譯器將不會自動構建賦值運算符;這樣你就可以決定應該如何處理分配......以及在那裏使用引用是否是個好主意:) –

0

priority_queue<...>::push使用(有效)push_heap算法。 push_heap算法要求元素是可複製分配的。 Ergo,priority_queue<...>::push要求元素是可複製分配的。

您的問題源於存儲引用,它沒有正確的分配語義。分配它們時,它會分配參照物,但不會重新參照參考。如果你想要可重新引用的引用,然後使用指針。