Я пытаюсь создать функцию для копирования класса, который имеет члены-указатели, поэтому указатели указывают на копию, а не на оригинал. В одном конкретном случае я не хочу, чтобы изменения переносились на оригинал.
Проблема возникает, когда деструктор вызывается до удаления объекта BoardState
. Поэтому, когда функция Copy
вызывается снова, она пытается удалить указатели и не может этого сделать, потому что они уже были удалены.
Странно то, что если я удаляю деструктор, все работает. Поэтому я думаю, что если объект был уничтожен, но указатели не были удалены, выделенная память будет отделена от указателей и приведет к утечке памяти. Однако этого не происходит. Указатели все еще сохраняют свои значения. Поэтому мне кажется, что деструктор вызывается без удаления объекта.
Я знаю, что могу использовать умные указатели и не беспокоиться об использовании деструктора, но я хочу получить от этого опыт обучения. Поэтому я надеялся, что кто-нибудь сможет рассказать мне, что происходит.
Функция копирования:
void BoardState::Copy(BoardState state)
{
copy = true;
if (p1 != nullptr) {
delete p1;
}
p1 = new Pawn(state.getP1());
if (p2 != nullptr) {
delete p2;
}
p2 = new Pawn(state.getP2());
if (walls != nullptr) {
delete walls;
}
walls = new list<Wall>(state.getWalls());
}
Destructor:
BoardState::~BoardState()
{
if (copy) {
if (p1 != nullptr) {
delete p1;
}
if (p2 != nullptr) {
delete p2;
}
if (walls != nullptr) {
delete walls;
}
}
}
В конце этой функции вызывается деструктор для SimulatedBoard
:
bool AI::startThinking(Pawn& pawn, Board& board)
{
simulatedBoard.Copy(board.getBoardState());
allPossibleDecision.clear();
plan.clear();
WallOptions.clear();
if (!thinking) {
thinking = true;
}
PathFinder pf(simulatedBoard);
list<sf::Vector2f> path = pf.createPath(board.getPawn(m_turnPos)->getPawn().getPosition(), sf::Vector2f(0, m_goal));
int opponent_turnPos = 1;
if (m_turnPos == 1) {
opponent_turnPos = 2;
}
int opponent_goal = 160;
if (m_goal == 160) {
opponent_goal = 640;
}
list<sf::Vector2f> opponent_path = pf.createPath(board.getPawn(opponent_turnPos)->getPawn().getPosition(), sf::Vector2f(0, opponent_goal));
int difference = opponent_path.size() - path.size();
int i;
if (difference < 0 && totalWalls > 0) {
i = 1;
}
else {
i = 2;
}
switch (i) {
case 1: {
list<decision>::iterator nextMove;
Wall placeWall;
bool foundBetterDifference = false;
addWallOptions(sf::Vector2f(190, 190),
simulatedBoard.getPawn(m_turnPos).getPawn().getPosition(),
simulatedBoard.getPawn(opponent_turnPos).getPawn().getPosition());
for (list<decision>::iterator it = allPossibleDecision.begin(); it != allPossibleDecision.end(); it++) {
decision d = (*it);
Wall w(d.wallPlacement, wallColor);
if (d.rotateWall) {
w.Rotate();
}
simulatedBoard.addWall(w);
opponent_path = pf.createPath(board.getPawn(opponent_turnPos)->getPawn().getPosition(), sf::Vector2f(0, opponent_goal));
path = pf.createPath(board.getPawn(m_turnPos)->getPawn().getPosition(), sf::Vector2f(0, m_goal));
simulatedBoard.removeWall(w);
int newDifference = opponent_path.size() - path.size();
if (newDifference > difference) {
foundBetterDifference = true;
difference = newDifference;
nextMove = it;
placeWall = w;
}
}
if (foundBetterDifference) {
board.addWall(placeWall);
plan.push_back(*nextMove);
totalWalls--;
break;
}
}
case 2 :
decision d;
d.movePawn = true;
d.pawnPos = path.front();
plan.push_back(d);
board.getPawn(m_turnPos)->getPawn().setPosition(path.front());
}
return false;
}
SimulatedBoard
не создается внутри этой функции. Это член класса. Даже если класс выходит из области видимости и это то, что удаляет SimulatedBoard
, в следующий раз, когда класс снова окажется в области видимости, конструктор должен запустить для SimulatedBoard
и установить указатели обратно на nullptr
. Если мое понимание неверно, что вполне может быть.