2013-06-01 171 views
-3

我是一個完整的初學者在C++中,一切都一直很好,直到現在。我是新來的指針的想法(我來自python),我有這個奇怪的錯誤。因此基本上,我創建了這個「SearchNode」類,下面找到它的一個方法「getChildren」,它應該返回其他SearchNode實例的向量,表示Knight(棋盤)可以從中移動的可能單元格這是目前的狀態。 (BFS)C++向量中的所有元素指向相同的元素

也就是說,當我完成推入我的向量時,所有元素突然指向第一個元素。有人可以幫我在這裏嗎?

PS:這與 c++ push_back doesn't work as it is supposed類似的問題...但與Angela(誰在編寫自己的編譯器)不同,我是C++的初學者。您的幫助將不勝感激。

UPDATE

我擺脫了INT *,並使用陣列我的狀態。我現在可以成功搜索圖表(因此狀態正常)並找到最短路徑,但似乎無法重建路徑。

爲了測試,我從{0,0}開始,可以找到{4,4},但根據getPath方法的路徑是{4,4},{3,6},{3,6 },{3,6} ...({3,6}的無限循環)。我的父指針或我的getPath函數有問題嗎?感謝您的支持提前。

//Search class 
class SearchNode 
{ 
public: 
//Variables 
SearchNode *m_parent; 
array<int,2> m_state; //I don't understand typedef's yet, will use them when I'm clearer with them :) 

//Normal Constructor 
SearchNode(array<int,2>& state_, SearchNode *parent_=nullptr) : 
m_state(state_), 
m_parent(parent_) 
{} 


//Method to get Next reachable states. Returns instances of SearchNode. 
vector<SearchNode> getChildren() 
{ 
    int legalMoves[8][2] = {{1,2},{1,-2},{-1,2},{-1,-2},{2,1},{2,-1},{-2,1},{-2,-1}}; 

    vector<SearchNode> children; 
    children.reserve(8); 
    for(int i=0; i<8; i++) 
    { 
     int x = (m_state[0] + legalMoves[i][0]); 
     int y = (m_state[1] + legalMoves[i][1]); 
     if((x>-1) and (x<9) and (y<9) and (y>-1)) // Within the bounds of the board 
     { 
      array<int,2> childState = {x,y}; 
      SearchNode childNode = SearchNode(childState,this); 
      children.push_back(childNode); 
     } 
    } 
    return children; 
} 

void getPath() 
{ 
    cout<<"\nPath: "; 
    cout<< this->print(); 
    SearchNode current = *this; 
    unsigned int counter = 1; 
    while((current.m_parent!=nullptr) and counter< 10) 
    { 
     counter++; 
     cout<< (current.m_parent)->print(); 
     current = *(current.m_parent); 
    } 
    cout << (current.m_parent)->print(); 
} 

string print() 
{ 
    stringstream out; 
    out << "{" << this->m_state[0] << "," << this->m_state[1] << "} "; 
    return out.str(); 
} 
}; 
+4

'SearchNode'是否有合理的拷貝構造函數? –

+3

你在照顧[this](http://stackoverflow.com/questions/4172722/what-is-the-rule-of-reeree)嗎? –

+0

你在調試器中看過for循環嗎? – ChiefTwoPencils

回答

6

很多錯誤和錯誤,我強烈建議您在編譯器中調出警告級別,以便獲得更多信息。正如Mookbear指出的那樣,使用GCC/G ++/Clang,可以嘗試「-Wall」或「-Wextra」。

您的節點永遠不會被分配「父」值,您正在創建一個稱爲「父」的「影子」局部變量並指定它。爲了避免這樣的常見錯誤,使用成員變量名稱的前綴或後綴來將它們與本地名稱分開,例如, 「m_parent」或「_parent」。

您不要在構造函數中分配默認值,而是明確地將值保留爲未初始化值。

SearchNode() 
{ 
    //do nothing 
} 

,然後你介紹在基於指針的構造這個垃圾數據,你可能想要的是

SearchNode() : parent(NULL), state(NULL) {} 

你的拷貝構造函數是一個災難。你需要閱讀並理解指針和局部變量。

//Start Node constructor. Still looking for an equivalent for null. 
SearchNode(int *state) 
{ 
    int genericStartState[2] = {-1,-1}; 
    SearchNode blankParent = SearchNode(); 
    SearchNode genericStart = SearchNode(genericStartState,&blankParent); 
    this->parent = &genericStart; 
    this->state=state; 
} 

首先,「blankParent」這裏是包含因爲你當前的拷貝構造函數的隨機數據的局部變量。其次,你正在接受它的地址 - 一個私有局部變量,當你在程序結束時點擊「}」時,它將停止存在。

「genericStartState」也即將超出範圍。

除此之外,我不認爲你想要或需要這個特定的構造函數。

但從根本上說,你的主題中的錯誤是因爲你在你的賦值循環中做了同樣的事情 - 你使用臨時的本地數組來存儲新值,然後將一個指針傳遞給你的構造函數。由於您正在使用該地址,因此每個循環都是相同的。

int childState[2] = { x, y }; 
    SearchNode childNode = SearchNode(childState,this); 

這就是爲什麼所有的節點都具有相同的狀態 - 因爲它們都指向同一個內存位置(編輯:由DYP指出的,副作用是不是你可以指望,只是在這種情況下訂購的人造物)。

您可能更容易使用簡單的inint數組,而不是節點結構中的指針。

如果您的編譯器是VisualStudio 2012或G ++ 4.8或Clang 4.2,以下是構造函數的外觀。

class SearchNode 
{ 
public: 
    typedef std::array<int, 2> State; 

private: 
    // I use the 'm_' convention for members, 'g_' for globals, 's_' for statics. 
    SearchNode* m_parent; 
    State  m_state; 

public: 
    ////////// 
    // Default ctor. 
    SearchNode() 
     : m_parent(nullptr) // C++11 constant meaning pointer with value 0 
     , m_state({-1, -1}) // preferred but requires recent C++11 features 
    { 
     //m_state[0] = m_state[1] = -1; // had to do this instead for gcc 4.7.3 
    } 

    ////////// 
    // Normal ctor 
    // I use the '_'-postfix convention for parameter names. 
    SearchNode(SearchNode* parent_, const State& state_) 
     : m_parent(parent_) 
     , m_state(state_) 
    { 
    } 

    ////////// 
    // Copy constructor. 
    // We could do this, but it's the default behavior anyway. 
    /* 
    SearchNode(const SearchNode& rhs) 
     : m_parent(rhs.m_parent) 
     , m_state(rhs.m_state) 
    { 
    } 
    */ 

    // Current C++11 compilers let us be explicit and do this: 
    //SearchNode(const SearchNode& rhs) = default; 

    // But it's the default behavior so we don't have to do this one at all. 
}; 

最新的C++語言的11個變化(MSVC> 2012年,GCC> = 4.8,鏘> = 4.1)將讓你與

// Kill two birds with one stone and have default parameters on our normal ctor, 
// replacing both the default and normal ctor with one function. 
SearchNode(SearchNode* parent_ = nullptr, const State& state_ = { -1, -1 })) 
    : m_parent(parent_) 
    , m_state(state_) 
{  
} 

如果你有更換前兩個構造函數一個完全C++ 1y兼容的編譯器,你可以把所有的東西燒到:

class SearchNode 
{ 
public: 
    typedef std::array<int, 2> State; 

private: 
    // I use the 'm_' convention for members, 'g_' for globals, 's_' for statics. 
    SearchNode* m_parent = nullptr; // c++1y keyword to replace 'NULL' 
    State  m_state = { -1, -1 }; 

public: 
    SearchNode() = default; 
      SearchNode(const State& rhs_) = default; // not strictly required. 
    SearchNode(SearchNode* parent_, const State& state_) 
     : m_parent(parent_), m_state(state_) 
     {} 
}; 
+0

對於GCC,-Wextra在啓動警告級別時也是一個明智的想法。雖然在使用Wextra的時候,我還沒有測試叮噹中的侍從的質量,但是對於GCC來說,它幫助我解決了許多大腦屁蟲的問題。 – moshbear

+0

@moshbear將其添加到文本中 – kfsone

+0

@kfsone非常感謝您爲指出我的錯誤付出的努力。說實話,你幾乎使我感到沮喪,但我從另一個角度來看待它,現在我迫不及待地想要達到你的這種語言水平。 :D我沒有人教我C++,但我認爲像你這樣的回覆,我並不需要老師:D再次感謝。 – John