我正在尝试创建一个函数来复制具有指针成员的类,因此指针指向的是副本而不是原始副本。在某些特定情况下,我不希望更改保留到原始版本中。
问题是在删除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());
}
析构函数:
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
运行,并将指针设置回{{1} }。除非我的理解是错误的,否则很可能是这样。
答案 0 :(得分:1)
我建议您为BoardState类定义一个合适的copy constructor,而不要使用Copy函数。
我假设在update t
set diff = datediff(day1, day2);
行上,SimulationBoard通过值传递给PathFinder的构造函数。 PathFinder pf(simulatedBoard)
的结果将使用SimulationBoard副本的析构函数。
由于SimulationBoard具有pf(simulatedBoard)
,因此其副本也将具有此标志,因此将为copy = true
,delete
和p1
指针调用p2
。
请注意,在复制函数中也发生了同样的事情(析构函数将从walls
参数中调用)。在为BoardState定义副本构造函数之前,请勿按值传递它,因为生成的副本将带有“ copy = true”标志。