我是c ++的初学者,到目前为止一直都很顺利。我对指针的想法很新(我来自python),我有这个奇怪的错误。
所以基本上,我创建了这个“SearchNode”类,并且在下面找到的是其中一个方法“getChildren”,它应该返回其他SearchNode实例的向量,表示Knight(棋盘)可以从中移动的可能单元格当前状态。 (BFS)
那就是说,当我完成推入向量时,所有元素突然只指向第一个元素。有人可以帮助我吗?
PS:这与c++ push_back doesn't work as it is supposed的问题类似......但与Angela(她正在编写自己的编译器)不同,我是c ++的初学者。非常感谢您的帮助。
更新
我摆脱了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();
}
};
答案 0 :(得分:6)
很多错误和错误,我强烈建议您在编译器中调高警告级别,以便获得更多信息。使用GCC / G ++ / Clang,尝试“-Wall”或“-Wextra”,正如moshbear指出的那样。
您的节点永远不会被分配“父”值,您正在创建一个名为“父”的“影子”局部变量并指定它。为了避免像这样的常见错误,请使用成员变量名称的前缀或后缀将它们与本地名称分开,例如: “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所指出的那样,副作用不是你可以指望的东西,只是一个人工制品在这种情况下订购)。
在节点结构中使用简单的int数组而不是指针可能更容易。
如果您的编译器是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&gt; 2012,GCC&gt; = 4.8,Clang&gt; = 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_)
{}
};