Назначение и удаление указателей - PullRequest
2 голосов
/ 28 октября 2011

Хорошо, так вот контекст.Я уже почти целый день работаю над легендарной проблемой из 8 головоломок.У меня отключена эвристика и отключен алгоритм A_star.Спецификация проекта требует от нас решения, используя три различных эвристических значения.Я могу решить ее для любого из трех по отдельности, но когда я решаю их последовательно, я получаю смешную петлю, и она никогда не находит правильное состояние преемника.

Я полагаю моя проблема с моими указателями.У меня есть класс State, как определено ниже, который имеет массив int ** и указатель на State (его родитель).

EDIT: мне нужно использовать 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 неверен (или оба).

Спасибо за ваше время и помощь,

Тайлер

Ответы [ 3 ]

2 голосов
/ 28 октября 2011

Обновление вашего стиля кода может привести к испарению ошибок.Другими словами 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 голос
/ 28 октября 2011

Вы не показываете полное определение конструктора копирования, но я предполагаю, что там есть строка parent = other.parent.В этом случае родитель не будет нести ответственность за свое собственное время жизни, и delete parent в деструкторе вообще не должно существовать.

Также обратите внимание, что вам нужно как минимум отключить (частное объявление) илиреализовать оператор присваивания копии.

Еще лучше, используйте vector из vector для вашего 2d массива и позвольте языку работать для вас.

0 голосов
/ 28 октября 2011

Возможно, это не прямой ответ, но вы идете вразрез с лучшими практиками для 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;
};
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...