好的,所以这是上下文。我已经连续工作了近一天,正在研究传奇的8-puzzle问题。我有我的启发式算法,我的A_star算法失效了。项目规范要求我们使用三种不同的启发式值来解决它。我可以单独为三个中的任何一个解决它,但是当我连续解决它们时,我得到一个荒谬的循环,它永远找不到正确的继承状态。
我相信我的问题在于我的指针。我有一个类,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。我只是无法弄明白。我觉得我的删除父错误或我的 parent = other.parent 错误(或两者兼而有之)。
感谢您的时间和帮助,
泰勒
答案 0 :(得分:2)
升级代码样式可能会导致错误消失。换句话说,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
,编译器将负责其余的工作。
答案 1 :(得分:1)
您没有显示复制构造函数的完整定义,但我假设parent = other.parent
行在那里。在这种情况下,父母不会对其自己的生命负责,并且析构函数中的delete parent
根本不存在。
另请注意,您至少需要禁用(私有声明)或实现复制赋值运算符。
更好的是,为{2}数组使用vector
vector
,让语言为您服务。
答案 2 :(得分:0)
也许不是直接的答案,但是你反对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++;
使用上述策略也可以更轻松地处理多维数组。它只是打破了。如果你真的想要行/ col访问,请在它周围写一个包装器。
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;
};