破坏者的顺序

问题描述 投票:-2回答:1

我有这样的课程:

游戏:

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;
    }
}

BoardField:

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

在程序结束时我在~BordField中出错:

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

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

c++ destructor object-lifetime
1个回答
1
投票

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

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

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

  • 如果m_board_fields是固定大小的二维数组,则使其成为固定大小的数组(又名BoardField* m_board_fields[8][8])。如果要保持动态大小,请使用向量。
  • 如果预期存在某些多态性,则m_board_field的单元格可以是指针。但这似乎不是这里的情况,因为显然ChessPiece是多态类。所以最好使用普通字段而不是指针(又名BoardField m_board_fields[8][8])。
  • 最后,不要使用原始指针到ChessPiece,更好地使用shared_ptr<ChessPiece>:你不必担心浅指针副本和双删除;如果不再使用,shared_ptr会照顾好自己并摧毁物体。
© www.soinside.com 2019 - 2024. All rights reserved.