对象数组,Java和C ++之间的区别

时间:2014-09-24 11:25:39

标签: java c++ arrays

我是C ++的新手,我正在将Java项目移植到C ++。

考虑以下Java代码,其中Piece是代表棋子的类:

Piece[][] myPieces = new Piece[8][8];

它创建一个数组,其中所有条目都为空。

如何在C ++中实现相同的功能?我试过了:

Piece* myPieces = new Piece[8][8];

但是这将创建一个数组,其中所有条目都使用默认构造函数初始化。

由于

编辑:我希望C ++代码高效/优雅,我不关心也不想将粘贴从Java复制到C ++。如果需要,我很乐意大量修改代码结构。

编辑2:代码适用于国际象棋程序,数组的大小将从不更改且性能至关重要。

9 个答案:

答案 0 :(得分:7)

在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

答案 1 :(得分:5)

正如你想要的那样,并且适合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;

答案 2 :(得分:3)

答案取决于,因为与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对象被销毁时,实际的部件本身也会被销毁。

答案 3 :(得分:2)

在C ++中,您可以执行以下操作:

std::vector<std::vector<std::unique_ptr<Pieces>>> myPieces;

答案 4 :(得分:2)

语义上相同的是:

Piece* myPieces[8][8]

因为java只知道堆上的对象,指针。

由于片段可能不是最后一堂课,但有国王,女王,这是要走的路。

答案 5 :(得分:1)

在c ++中,使用默认构造函数创建新创建的对象(甚至在数组中)。这是与java的重要区别之一。如果你想单独调用构造函数,只需使用向量向量并添加它们中的每一个。

答案 6 :(得分:1)

我对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

答案 7 :(得分:1)

所以你想制作一个国际象棋引擎,性能至关重要。有几个在线教程。速度对于国际象棋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。

答案 8 :(得分:0)

在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