析构函数顺序

Order of destructors

我有这些类:

游戏:

class Game {
private:
    BoardField*** m_board_fields;
public:
    Game() { 
        m_board_fields = new BoardField**[8];
        for (int i = 0; i < 8; i++) {
             m_board_fields[i] = new BoardField*[8]; 
        }
    }

    Game::~Game() {
        for (int i = 0; i < 8; i++) {
            for (int j = 0; i < 8; j++) {
                delete m_board_fields[i][j];
            }

            delete[] m_board_fields[i];
        }

        delete[] m_board_fields;
    }
}

板场:

class BoardField {
private:
    ChessPiece* m_piece;
    ....
public:
    BoardField::~BoardField() {
        delete m_piece;
    }
}

并且在程序结束时我在 ~BordField:

中得到错误

Exception thrown: read access violation. this was 0xFDFDFDFD.

我的析构函数不正确吗?从多维数组中清除内存的最佳方法是什么?

您的设计存在两个根本性缺陷:

  • BoardField 没有明确的所有权:有人创建,有人删除。如果您非常谨慎,它可以工作,但它很容易出错。
  • 您不确保 rule of 3 (or better 5):如果您有任何一段代码,您可以在其中创建 Game 或任何 BoardField 的第一个对象的副本destroyed 将删除 m_piece 指针,当第二个对象被销毁时,它会尝试第二次删除同一个指针,即 UB。

还有第三个重要问题:你是 over-using 原始指针:

  • 如果m_board_fields是一个固定大小的二维数组,使它成为一个固定大小的数组(又名BoardField* m_board_fields[8][8])。如果你想保持它的大小动态,使用向量。
  • 如果预期存在某种多态性,m_board_field 的一个单元格可以是一个指针。但这里似乎不是这种情况,因为显然 ChessPiece 是多态的 class。所以最好使用普通字段而不是指针(又名 BoardField m_board_fields[8][8])。
  • 最后,与其使用指向 ChessPiece 的原始指针,不如使用 shared_ptr<ChessPiece> :您不必担心浅指针复制和双重删除; shared_ptr 将自行处理并销毁不再使用的对象。