好的,这是上下文。我已经连续工作了将近一天来解决传说中的8个谜题。我有了启发式和a *算法。项目规范要求我们使用三种不同的启发式值来解决它。我可以单独解决这三个中的任何一个,但是当我连续解决它们时,我得到一个荒谬的循环,它永远不会找到正确的后继状态。
我相信我的问题是我的指针。我有一个类State,如下所定义,它有一个int**数组和一个指向State(其父)的指针。
编辑:我必须使用项目规范定义的int**,否则我很乐意使用指针。
State (int **bd, State* prnt);
State (const State& other);
~State ();
然后我这样声明它们:
State::State(int **bd, State* prnt) {
// allocate the board
board = new int*[3];
for (int i = 0; i < 3; i++) {
board[i] = new int[3];
}
// fill in the board
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
board[i][j] = bd[i][j];
//board[i][j] =
}
}
// set the parent
parent = prnt;
}
State::State(const State& other) {
// allocate the board
board = new int*[3];
for (int i = 0; i < 3; i++) {
board[i] = new int[3];
State::~State() {
//std::cout << "Deconstructing " << this << endl;
for (int i = 0; i < 3; i++)
delete board[i];
delete [] board;
delete parent;
parent = other.parent;
}
State::~State() {
//std::cout << "Deconstructing " << this << endl;
for (int i = 0; i < 3; i++)
delete board[i];
delete [] board;
delete parent;
}
State& State::operator=(const State &rhs) {
if (&rhs == this) {
return *this;
}
for (int i = 0; i < 3; i++) {
delete board[i];
}
delete [] board;
// allocate the board
board = new int*[3];
for (int i = 0; i < 3; i++) {
board[i] = new int[3];
}
// fill in the board
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
//board[i][j] = rhs.board[i][j];
board[i][j] = rhs.getIntAtCoor(j, i);
}
}
//delete parent;
// set the parent
parent = rhs.parent;
// set g
g = rhs.g;
f = rhs.f;
hType = rhs.hType;
return *this;
}
我没有给出确切的声明——其中一些很简单,比如int = int。我只是不太明白。我觉得要么是我的delete parent错了,要么是我的parent = other。Parent 错误(或两者都错误)。
感谢您的时间和帮助,
泰勒升级代码样式可能会使错误消失。换句话说,new
和delete
容易出错,当存在更好的替代方案时应避免使用。
对于细胞的管理考虑:
-
std::shared_ptr
:可取消delete
呼叫 -
std::vector
可以用来避免new
和delete
调用
注意,您应该像使用std::vector<int> board( 3 * 3 )
和board.at( x + y * 3 )
一样使用它。最好的是使用静态数组int board[3][3]
。没有分配。
子状态也不拥有它们的父状态。这是反过来的。所以孩子不应该删除他们的父母。您仍然可以安全地保留父指针,但要确保在允许父指针超出作用域(删除或其他)之前清除了子指针。所有这些清理和删除都不一定涉及到新的内容。您的State
类看起来足够小,如果它们按值复制并不重要。在这种情况下,只需让父类使用std::vector<State> m_children
,编译器将负责其余部分。
您没有显示复制构造函数的完整定义,但我假设parent = other.parent
行在那里。在这种情况下,父类不应该对自己的生命周期负责吗?析构函数中的delete parent
根本不应该存在。
还需要注意,您至少需要禁用(私有声明)或实现复制赋值操作符。
更好的是,为你的2d数组使用vector
或vector
,让语言为你工作。
也许这不是一个直接的答案,但是你违背了c++的最佳实践。
用向量来解决这个问题更容易,也更容易维护。
size_t row_sz = 3;
size_t col_sz = 3;
std::vector<int> board(row_sz * col_sz, 0);
int i = 0;
for (size_t r = 0; r < 0; r++)
for (size_t c = 0; c < 0; c++)
board[ r * row_sz + c ] = i++;
使用上述策略处理多维数组也容易得多。它只是更少断裂。如果您确实需要行/列访问,请编写一个包装器。
struct Matrix {
int &operator()(size_t r, size_t c);
const int &operator()(size_t r, size_t c) const;
private:
std::vector<int> data;
};