析构函数的顺序

福斯塔斯·布库斯

我有这样的课程:

游戏:

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 中出现错误

抛出异常:读取访问冲突。这是 0xFDFDFDFD。

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

克里斯托夫

你的设计有两个基本缺陷:

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

还有第三个重要问题:您过度使用原始指针:

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

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

TOP 榜单

热门标签

归档