析构函数顺序
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
将自行处理并销毁不再使用的对象。
我有这些类:
游戏:
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
将自行处理并销毁不再使用的对象。