C++开发象棋引擎调用std::cout后Piece指针二维数组损坏求助
问题根源
你在Chess类构造函数中定义的Rook bq_r(black)、Knight bq_n(black)等所有棋子实例都是栈上的局部临时对象,它们的生命周期仅存在于构造函数执行阶段。构造函数执行结束后,这些局部对象占用的栈内存会被系统回收复用,存储在board数组里的指针全部变成悬垂指针,后续访问这些指针指向的内存属于未定义行为,就会出现输出乱码、内容随机变化、数组莫名损坏的现象。
你调试看到的print_board刚进入时数组内容正常,是因为此时对应栈内存还未被其他操作覆盖;执行std::cout操作会占用栈空间修改废弃内存,就出现了执行一次输出后数组损坏的现象。
修复方案
这里提供两种适配不同需求的修复方案:
方案1:堆内存存储棋子实例(灵活度高)
用new关键字在堆上创建棋子对象,堆对象的生命周期可以手动控制,不会随构造函数结束销毁:
// 修改chessBoard.cpp中的构造函数 Chess::Chess() { // 黑方后排棋子,改为堆上创建 board[0][0] = new Rook(black); board[0][1] = new Knight(black); board[0][2] = new Bishop(black); board[0][3] = new Queen(black); board[0][4] = new King(black); board[0][5] = new Bishop(black); board[0][6] = new Knight(black); board[0][7] = new Rook(black); // 其余位置棋子同理创建 }
需要额外给Chess类添加析构函数,遍历数组释放堆内存避免泄漏:
// chessBoard.h中添加析构声明 class Chess { private: Piece* board[8][8] = {}; public: Chess(); ~Chess(); void print_board(); }; // chessBoard.cpp实现析构逻辑 Chess::~Chess() { for (int i = 0; i < 8; i++) { for (int j = 0; j < 8; j++) { delete board[i][j]; } } }
方案2:棋子作为Chess类成员(性能更高,适合引擎场景)
把所有棋子实例定义为Chess类的成员,生命周期和Chess对象绑定,不需要手动管理内存:
// chessBoard.h修改私有成员 class Chess { private: // 预先定义所有棋子成员 Rook bq_r{black}, bk_r{black}, wq_r{white}, wk_r{white}; Knight bq_n{black}, bk_n{black}, wq_n{white}, wk_n{white}; Bishop bq_b{black}, bk_b{black}, wq_b{white}, wk_b{white}; Queen b_q{black}, w_q{white}; King b_k{black}, w_k{white}; Pawn b_pawns[8]{{black},{black},{black},{black},{black},{black},{black},{black}}; Pawn w_pawns[8]{{white},{white},{white},{white},{white},{white},{white},{white}}; Piece* board[8][8] = {}; public: Chess(); void print_board(); }; // chessBoard.cpp构造函数直接赋值成员地址 Chess::Chess() { board[0][0] = &bq_r; board[0][1] = &bq_n; board[0][2] = &bq_b; board[0][3] = &b_q; board[0][4] = &b_k; board[0][5] = &bk_b; board[0][6] = &bk_n; board[0][7] = &bk_r; // 其余赋值逻辑不变 }
内容的提问来源于stack exchange,提问作者kiran_isaac
相关产品推荐
相关产品推荐

