-3

我是一个完整的 C++ 初学者,直到现在一切都进行得很顺利。我对指针的想法很陌生(我来自 python),我有这个奇怪的错误。

所以基本上,我创建了这个“SearchNode”类,并在下面找到它的方法之一“getChildren”,它应该返回其他 SearchNode 实例的向量,表示骑士(棋盘)可以从当前状态移动到的可能单元格。(BFS)

也就是说,当我完成推入向量时,所有元素突然只指向第一个元素。有人可以帮我吗?

PS:这是一个与 c++ 类似的问题push_back 不能按预期工作......但与 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();
}
};
4

1 回答 1

6

很多错误和错误,我强烈建议您在编译器中调高警告级别,以便获得更多信息。正如 moshbear 指出的那样,使用 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 指出的那样,副作用不是您可以指望的,只是在此排序的人工制品案子)。

在节点结构中使用简单的整数数组而不是指针可能更容易。

如果您的编译器是 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,Clang >= 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_)
        {}
};
于 2013-06-02T04:50:44.360 回答