我是C ++的新手,我正在将Java项目移植到C ++。
考虑以下Java代码,其中Piece是代表棋子的类:
Piece[][] myPieces = new Piece[8][8];
它创建一个数组,其中所有条目都为空。
如何在C ++中实现相同的功能?我试过了:
Piece* myPieces = new Piece[8][8];
但是这将创建一个数组,其中所有条目都使用默认构造函数初始化。
由于
编辑:我希望C ++代码高效/优雅,我不关心也不想将粘贴从Java复制到C ++。如果需要,我很乐意大量修改代码结构。
编辑2:代码适用于国际象棋程序,数组的大小将从不更改且性能至关重要。
答案 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