[英]Array of objects, difference between Java and C++
我是C ++的新手,我正在將Java項目移植到C ++。
考慮以下Java代碼,其中Piece是表示棋子的類:
Piece[][] myPieces = new Piece[8][8];
它創建一個數組,其中所有條目都為null。
如何在C ++中實現相同的功能? 我試過了:
Piece* myPieces = new Piece[8][8];
但是這將創建一個數組,其中所有條目都使用默認構造函數初始化。
謝謝
編輯:我希望C ++代碼高效/優雅,我不關心也不想將粘貼從Java復制到C ++。 如果需要,我很樂意大量修改代碼結構。
編輯2:代碼用於國際象棋程序,數組的大小永遠不會改變,性能至關重要。
在C ++中聲明一個8x8可選對象數組的最簡單方法是這樣的:
boost::optional<Piece> myPieces[8][8];
boost::optional
類型表示一個可選對象(就像Java中的可空引用一樣),它沒有使用指針類型的所有缺陷。 它應該在未來幾年作為標准庫的一部分提供。
您可能更喜歡使用std::array
類型,它是固定大小數組的封裝,允許將它們視為一等公民,並提供更好的界面:
std::array<std::array<boost::optional<Piece>, 8>, 8> myPieces;
如果您希望能夠在運行時調整數組大小,請考慮使用std::vector
。
正如你想要的那樣,並且正確的C ++而不是愚蠢的翻譯,這是怎么回事:
使用尺寸為1的POD型件。
添加您可能想要的所有便利方法:
struct Piece {
unsigned char value;
constexpr Piece() : value() {}
constexpr operator bool() const {return !value;}
constexpr bool empty() const {return *this;};
constexpr bool black() const {return value&0x80;}
constexpr bool white() const {return value && !black();}
constexpr unsigned piece() const {return value & 0x7f;}
};
現在這將是一個等效的原始數組:
Piece board[8][8];
或者使用std::array
:
#include <array>
std::array<std::array<Piece, 8>, 8> board;
答案取決於,因為與Java相反,在C ++中,您擁有不同的所有權語義和對象生命周期管理(兩者齊頭並進)。
如果你想模擬類似於java的對象,你會寫:
using PiecePtr = std::shared_ptr<Piece>;
std::array<std::array<PiecePtr, 8>, 8> Pieces;
shared_ptr具有與java對象類似的語義(在任何地方傳遞它,只要有對它的引用就保證它的生命周期)。
如果你想對觀察到的對象進行建模(即數組不擁有它們),你應該寫:
using PiecePtr = Piece*;
std::array<std::array<PiecePtr, 8>, 8> Pieces;
這確保了當Pieces
對象被銷毀時,實際的片段本身仍保留在內存中。
如果要為Pieces
數組擁有的唯一對象建模,則應使用:
using PiecePtr = std::unique_ptr<Piece>;
std::array<std::array<PiecePtr, 8>, 8> Pieces;
這確保了當Pieces對象被銷毀時,實際的部件本身也會被銷毀。
在C ++中你會做類似的事情:
std::vector<std::vector<std::unique_ptr<Pieces>>> myPieces;
語義上等價的將是:
Piece* myPieces[8][8]
因為java只知道堆上的對象,指針。
作為Piece可能不是最后一堂課,但有King,Queen,這是要走的路。
在c ++中,使用默認構造函數創建新創建的對象(甚至在數組中)。 這是與java的重要區別之一。 如果你想單獨調用構造函數,只需使用向量向量並添加它們中的每一個。
我沒有使用java的經驗,但我相信我得到的結果可能是C ++的一個很好的替代品:
std::array<std::array<unique_ptr<foo>, 8>, 8> arr = {};
if(arr[2][3].get() == nullptr) // Can check for null elements
std::cout << "this is null";
arr[3][4].reset(new foo()); // Initialize an element
所以你想制作一個國際象棋引擎,性能至關重要。 有幾個在線教程。 速度對於國際象棋AI來說很重要,所以它可以考慮每秒更多的動作,但你可能需要犧牲優雅。
您可以直接將塊值存儲在板陣列中,也可以將塊存儲在單獨的后備陣列中,並將板創建為指向這些塊的指針。 第二種方法有一些優點,我現在不記得了。
std::array<std::array<Peice *, 8>, 8> Board;
std::array<Piece, 32> Pieces;
您可以將空單元格表示為空指針。
如果你想要在同一個數組中的所有內容,你可以簡單地使用
std::array<std::array<Peice, 8>, 8> Board;
但是您需要創建一個“虛擬”片段值來表示空單元格。
注意,沒有動態內存分配,內存中的數據緊湊,因此緩存性能更好。
Piece可以是枚舉或具有一些有用的getter函數的結構,例如IsWhite。
在C ++中,您必須聲明為:
Piece *** myPieces;
然后,分配為:
myPieces = new Piece **[8];
然后,
for (int i = 0; i < 8; i++) {
myPieces[i] = new Piece *;
}
現在,如果你這樣做,
myPieces[0][0] = new Piece(); // C++, calls default constructor of Piece
在Java中
Piece[][] myPieces;
myPieces = new Piece[8][8];
現在,如果你這樣做,
myPieces[0][0] = new Piece(); // Java, calls default constructor of Piece
由於你已經知道了8x8,你也可以聲明為(在C ++中):
Piece * myPieces[8][8]; // 64 pointers preallocated as 8 rows, 8 cols
然后,
現在,如果你這樣做,
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 8; j++) {
myPieces[i][j] = new Piece(); // or new Pawn or new Knight etc, subclass of Piece
}}
或根據需要分配,例如
myPieces[0][0] = new Piece(); // or new Pawn or new Knight etc, subclass of Piece
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.