我有一个类方法,可以处理对象的副本(确切地说是*)。泄漏发生在重载的赋值运算符中 - 无论如何,这是Visual Leak Detector所说的。我正在做的是使用副本,如果完成的工作是令人满意的,我将新创建的对象复制回来。我还实现了自定义析构函数,复制构造函数和赋值运算符,因为问题出现在动态分配的内存中。我使用C ++的经验非常有限,因此代码中可能存在一些不好的东西。
如果需要,我会提供更多信息。
有问题的方法:
bool Grid::SurroundShipSquares(int top, int bottom, int left, int right)
{
// copying itself
Grid gridCopy(*this);
Square** squaresCopy = gridCopy.GetSquares();
for (int i = top; i <= bottom; ++i)
{
for (int j = left; j <= right; ++j)
{
if (squaresCopy[i][j].GetState() != SquareState::Vacant)
return false;
(squaresCopy[i][j]).SetState(SquareState::Unoccupiable);
}
}
// the problem occurs here
*this = gridCopy;
return true;
}
复制构造函数:
Grid::Grid(const Grid& source)
{
_position = source._position;
_size = source._size;
int dimensions = static_cast<int>(_size);
_squares = new Square*[dimensions];
for (int i = 0; i < dimensions; ++i)
{
_squares[i] = new Square[dimensions];
for (int j = 0; j < dimensions; ++j)
{
_squares[i][j] = source._squares[i][j];
}
}
}
作业运营商:
Grid& Grid::operator=(const Grid& source)
{
if (this == &source)
return *this;
_position = source._position;
_size = source._size;
int dimensions = static_cast<int>(_size);
_squares = new Square*[dimensions];
for (int i = 0; i < dimensions; ++i)
{
_squares[i] = new Square[dimensions];
for (int j = 0; j < dimensions; ++j)
{
_squares[i][j] = source._squares[i][j];
}
}
return *this;
}
析构函数:
Grid::~Grid()
{
int dimensions = static_cast<int>(_size);
for (int i = 0; i < dimensions; ++i)
{
delete[] _squares[i];
}
delete[] _squares;
}
答案 0 :(得分:5)
您的代码存在的问题是您手动管理所有资源。这是非常不安全的,并且正确地做了大量的头痛,正如现有的答案都是错误的恰当证明的那样。
使用std::vector
。该课程将自动为您管理所有内存,让您不必自己动手。这将大大简化您的代码,并使其正确。
此外,自我分配检查是一种古老的反模式。不要包括自我分配的检查。如果您的赋值运算符(在大多数情况下,您不应该自己编写自己的基于std::vector
的内存管理)在没有特殊情况下无法处理自我赋值,那么它就会被破坏。