C++ C++;-重载赋值运算符内存泄漏

C++ C++;-重载赋值运算符内存泄漏,c++,memory-leaks,operator-overloading,copy-constructor,assignment-operator,C++,Memory Leaks,Operator Overloading,Copy Constructor,Assignment Operator,我有一个类方法,可以处理对象的副本(*确切地说是this)。泄漏发生在过载的赋值操作符中——无论如何,这就是VisualLeakDetector所说的。我正在做的是复制,如果完成的工作令人满意,我会将新创建的对象复制回来。我还实现了一个自定义析构函数、复制构造函数和赋值运算符,因为问题显然发生在动态分配的内存中。我的C++经验非常有限,所以代码中可能有一些邪恶的东西。 如果需要,我会提供更多信息 有问题的方法: bool Grid::SurroundShipSquares(int top, in

我有一个类方法,可以处理对象的副本(*确切地说是this)。泄漏发生在过载的赋值操作符中——无论如何,这就是VisualLeakDetector所说的。我正在做的是复制,如果完成的工作令人满意,我会将新创建的对象复制回来。我还实现了一个自定义析构函数、复制构造函数和赋值运算符,因为问题显然发生在动态分配的内存中。我的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;
}
bool Grid::SurroundShipSquares(int-top、int-bottom、int-left、int-right)
{
//复制自己
网格副本(*此);
Square**squareScope=gridCopy.GetSquares();

对于(int i=top;i来说,代码的问题在于您需要手动管理所有资源。这是非常不安全的,而且要正确执行也是一件非常头疼的事情,现有的两个答案都是错误的,这一点很好地证明了这一点

使用
std::vector
。该类将自动为您管理所有内存,使您无需亲自操作。这将大大简化您的代码,并使其正确无误


此外,自分配检查是一种古老的反模式。不要包括自分配检查。如果您的分配运算符(在大多数情况下,您不应该真正需要使用基于
std::vector
的内存管理编写自己的自分配检查)没有特殊情况无法处理自我分配,它已损坏。

省去所有麻烦,改用。不幸的是,这个问题再次证明了为什么我最近在SE网络的这一部分的参与度下降了。@DavidHammen我很抱歉出现这种情况,但我肯定不是那个要说的人我。我所做的只是发布了一个诚实的新手问题。@Venom:你肯定不是该受责备的人。一方面,你应该认真考虑使用标准库中的工具。另一方面,你最终需要学会编写安全代码和正确管理资源。在这个网站上,有一群连续的反对者不要让别人回答你的问题。做Daniel Frey在他的评论中所说的。学习复制和交换习语。你应该考虑使用STD::向量,如果它适合你的需要。@ DavidHammen,你完全可以自由回答你所做的问题。其他人认为它有害,他们向你解释。(在评论部分)为什么?这是他们的选择。停止整个抱怨。我能用Val数组存储2D矩阵吗?我问,因为它肯定会保持固定的维度。例如,像STD::ValStudioSuaReScript。你可以这样做,但是考虑Booo::多进制数组。无论如何,你现有的代码相当于向量矢量。d::valarray有点像一个孤儿,没有人喜欢或使用它。最终,容器的确切选择取决于您想要表达的确切语义,并且在这里比首先使用一个更重要。通常,程序员只使用vector,除非他们特别需要使用其他东西。我注意到multi_数组的大小仍然需要在编译时知道,不幸的是,这在我的例子中不起作用。在我之前的评论中,我的意思是容器大小一旦最初确定,在其整个生命周期内保持不变。C++14提出了dynarray,但显然还没有可用的实现。对于dy,只需使用
std::vector
NAMICAL sized array和
std::array
用于静态大小的数组。就这么简单。@Venom:不。MSVC发出了一大堆完全虚假的警告。如果警告是从Boost代码中发出的,那么忽略它-Boost开发人员已经在寻找它了。基本上没有人使用/W4,因为编译器发出了太多无用的警告罗宁。
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;
}