簡體   English   中英

對象數組,Java和C ++之間的區別

[英]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
  • 智能指針可以避免內存泄漏
  • std :: array提供與普通C數組相當的性能
  • 聚合初始化為每個指針提供一個空值
  • 固定大小作為java數組

所以你想制作一個國際象棋引擎,性能至關重要。 有幾個在線教程。 速度對於國際象棋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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM