如何制作指针数组的深拷贝
How to make a deep copy of an array of pointers
我正在创建国际象棋引擎,我正在使用可以找到的国际象棋引擎 here 因为它是 ChessBoard 和 Piece classes。作为引擎的一部分,我必须对 ChessBoard class 的实例进行深度复制,而且我在执行此操作时遇到了很大的困难。我尝试以多种方式编辑 class 中的复制构造函数并更改我自己的代码,但无济于事。
这是我的代码中有问题的部分:
move_list = j->data().board->getPossibleMoves(board->flip(colour));
for (auto k : move_list) {
print_board(j->data().board);
current_node.board = j->data().board;
current_node.board->moveTo(std::tuple<char, char>(std::get<0>(k), std::get<1>(k)), std::tuple<char, char>(std::get<2>(k), std::get<3>(k)));
std::cout << "After :" << std::endl;
print_board(j->data().board);
j->insert(current_node);
//"j" is a node in a tree class
//"k" is structured like this: std::vector<std::tuple<char, char, char, char>>
//"MoveTo" moves a chess piece to a location on the chess board
这会产生如下输出:
Before :
R N B Q K B N R
P P P P P P P P
p p p p p p p p
R N B Q K B N R
After :
R N B Q K B N R
P P P P P P P P
p
p p p p p p p
R N B Q K B N R
如您所见,即使我更改了新的“ChessBoard”,“j->data()”的值也会发生变化,因此“j->data()”和新棋盘指向相同的位置在记忆中。
ChessBoard 和 Piece 的拷贝构造函数如下:
//board.h
ChessBoard(const ChessBoard& rhs) { //Copy constructor
//This is the section that I'm concerned about ↓ (Until the other comment)
for (int x = 0; x < 8; x++) {
for (int y = 0; y < 8; y++) {
Piece* piece = new Piece(rhs.squares[x][y]->colour);
piece->value = rhs.squares[x][y]->value;
piece->symbol = rhs.squares[x][y]->symbol;
piece->pieceType = rhs.squares[x][y]->pieceType;
piece->moveCount = rhs.squares[x][y]->moveCount;
ChessBoard::squares[x][y] = piece;
}
}
//This is the section that I'm concerned about ↑ (Until the other comment)
for (auto itr = rhs.promotedQueens.begin(); itr != promotedQueens.end(); ++itr) {
Piece piece = **(itr);
promotedQueens.push_back(&piece);
}
whiteCastled = rhs.whiteCastled;
blackCastled = rhs.blackCastled;
plyCount = rhs.plyCount;
allowIllegalMoves = rhs.allowIllegalMoves;
improvedDrawDetection = rhs.improvedDrawDetection;
ChessBoard::transpos_table.initializeHash(this, Colour::White);
initializeOriginalSquares();
}
//Pieces.h
Piece(const Piece& rhs) { //Copy constructor
value = rhs.value;
symbol = rhs.symbol;
pieceType = rhs.pieceType;
moveCount = rhs.moveCount;
colour = rhs.colour;
};
总而言之,我如何制作复制构造函数来制作 ChessBoard 的深层副本 class 或以其他方式创建它的深层副本?
您正在为您的片段使用运行时多态性。 IE。你有一个指向 Piece
的棋盘,它可以是不同类型的(Horse
、Bishop
等等)。你的问题是,当你复制构造你的棋盘时,你需要复制构造每一块,但你只持有一个 Piece*
到一个多态对象。你需要一个virtual copy constructor。根据 link 中的建议,您可以:
- 向您的
Piece
基础 class 添加一个纯虚拟 clone
方法,并且
- 为每个最终 classes 覆盖该方法,在那里进行复制构造。
下面的代码使用智能指针而不是原始指针。注意 *this
被传递给 std::make_unique
以调用复制构造函数。如果您什么都不传递,您将调用默认构造函数。这同样适用于使用原始指针和 new
.
class Piece {
public:
virtual std::unique_ptr<Piece> clone() = 0;
};
class Horse : public Piece {
public:
virtual std::unique_ptr<Piece> clone() override {
return std::make_unique<Horse>(*this);
};
};
ChessBoard(const ChessBoard& cb) {
for (size_t x{0}; x < board_size; ++x) {
for (size_t y{0}; y < board_size; ++y) {
squares[x][y] = cb.squares[x][y]->clone();
}
}
}
一些其他相关的 links:关于 virtual copy constructors. And two useful answers to that question, 1, and 2 的另一个问题。
我正在创建国际象棋引擎,我正在使用可以找到的国际象棋引擎 here 因为它是 ChessBoard 和 Piece classes。作为引擎的一部分,我必须对 ChessBoard class 的实例进行深度复制,而且我在执行此操作时遇到了很大的困难。我尝试以多种方式编辑 class 中的复制构造函数并更改我自己的代码,但无济于事。
这是我的代码中有问题的部分:
move_list = j->data().board->getPossibleMoves(board->flip(colour));
for (auto k : move_list) {
print_board(j->data().board);
current_node.board = j->data().board;
current_node.board->moveTo(std::tuple<char, char>(std::get<0>(k), std::get<1>(k)), std::tuple<char, char>(std::get<2>(k), std::get<3>(k)));
std::cout << "After :" << std::endl;
print_board(j->data().board);
j->insert(current_node);
//"j" is a node in a tree class
//"k" is structured like this: std::vector<std::tuple<char, char, char, char>>
//"MoveTo" moves a chess piece to a location on the chess board
这会产生如下输出:
Before :
R N B Q K B N R
P P P P P P P P
p p p p p p p p
R N B Q K B N R
After :
R N B Q K B N R
P P P P P P P P
p
p p p p p p p
R N B Q K B N R
如您所见,即使我更改了新的“ChessBoard”,“j->data()”的值也会发生变化,因此“j->data()”和新棋盘指向相同的位置在记忆中。
ChessBoard 和 Piece 的拷贝构造函数如下:
//board.h
ChessBoard(const ChessBoard& rhs) { //Copy constructor
//This is the section that I'm concerned about ↓ (Until the other comment)
for (int x = 0; x < 8; x++) {
for (int y = 0; y < 8; y++) {
Piece* piece = new Piece(rhs.squares[x][y]->colour);
piece->value = rhs.squares[x][y]->value;
piece->symbol = rhs.squares[x][y]->symbol;
piece->pieceType = rhs.squares[x][y]->pieceType;
piece->moveCount = rhs.squares[x][y]->moveCount;
ChessBoard::squares[x][y] = piece;
}
}
//This is the section that I'm concerned about ↑ (Until the other comment)
for (auto itr = rhs.promotedQueens.begin(); itr != promotedQueens.end(); ++itr) {
Piece piece = **(itr);
promotedQueens.push_back(&piece);
}
whiteCastled = rhs.whiteCastled;
blackCastled = rhs.blackCastled;
plyCount = rhs.plyCount;
allowIllegalMoves = rhs.allowIllegalMoves;
improvedDrawDetection = rhs.improvedDrawDetection;
ChessBoard::transpos_table.initializeHash(this, Colour::White);
initializeOriginalSquares();
}
//Pieces.h
Piece(const Piece& rhs) { //Copy constructor
value = rhs.value;
symbol = rhs.symbol;
pieceType = rhs.pieceType;
moveCount = rhs.moveCount;
colour = rhs.colour;
};
总而言之,我如何制作复制构造函数来制作 ChessBoard 的深层副本 class 或以其他方式创建它的深层副本?
您正在为您的片段使用运行时多态性。 IE。你有一个指向 Piece
的棋盘,它可以是不同类型的(Horse
、Bishop
等等)。你的问题是,当你复制构造你的棋盘时,你需要复制构造每一块,但你只持有一个 Piece*
到一个多态对象。你需要一个virtual copy constructor。根据 link 中的建议,您可以:
- 向您的
Piece
基础 class 添加一个纯虚拟clone
方法,并且 - 为每个最终 classes 覆盖该方法,在那里进行复制构造。
下面的代码使用智能指针而不是原始指针。注意 *this
被传递给 std::make_unique
以调用复制构造函数。如果您什么都不传递,您将调用默认构造函数。这同样适用于使用原始指针和 new
.
class Piece {
public:
virtual std::unique_ptr<Piece> clone() = 0;
};
class Horse : public Piece {
public:
virtual std::unique_ptr<Piece> clone() override {
return std::make_unique<Horse>(*this);
};
};
ChessBoard(const ChessBoard& cb) {
for (size_t x{0}; x < board_size; ++x) {
for (size_t y{0}; y < board_size; ++y) {
squares[x][y] = cb.squares[x][y]->clone();
}
}
}
一些其他相关的 links:关于 virtual copy constructors. And two useful answers to that question, 1, and 2 的另一个问题。