C ++による2D配列オブジェクトの取得と挿入
質問
1つの小さな2D配列オブジェクトから配列データメンバーを返そうとし、配列を大きな2D配列オブジェクトに挿入しようとしています。しかし、これを試みると、2つの問題が発生しました。
最初の問題は、2D配列の名前を返すことですが、2D配列名を返すための適切な構文の方法がわかりません。
これは私の2D配列データメンバーの外観です
private: int pieceArray[4][4]; // 2D Smaller Array
この配列を関数に返したいのですが、これによりコンパイラエラーが発生します:
int Piece::returnPiece() { return pieceArray; //not vaild // return the 2D array name }
この戻り値の型を使用するのに疲れて、うまくいきました:
int Piece::returnPiece() { return pieceArray[4][4]; }
しかし、配列とそのすべてのコンテンツを返したいので、これが私が望むものかどうかわかりません。
もう1つの問題はInsertArray()関数です。ここでは、InsertArray()の引数にreturnPiece()関数を配置します。
InsertArray()の問題は引数です。ここにコードがあります:
void Grid::InsertArray( int arr[4][4] ) //Compiler accepts, but does not work { for(int i = 0; i < x_ROWS ; ++i) { for (int j = 0; j < y_COLUMNS ; ++j) { squares[i][j] = arr[i][j]; } } }
これに関する問題は、returnPiece()を受け入れないことです。&quot; [4] [4]&quot;を削除すると、コンパイラは受け入れません。
これらのほとんどは構文エラーですが、これらの問題を解決するにはどうすればよいですか
- returnPiece()でpieceArray全体を返す
- InsertArray()の引数の正しい構文
- returnPiece()を受け入れるInsertArray()の引数
これら3つは私が助けを必要とする主要な問題であり、ポインターポインターメソッドを使用しようとしたときに同じ問題が発生しました。誰もがこれらの3つの問題を解決する方法を知っていますか?
解決
配列を渡すとき、配列のコピーを作成するかどうか、または配列へのポインタを返すだけかどうかを決定する必要があります。配列を返す場合、コピーを(簡単に)返すことはできません-ポインタ(またはC ++の参照)のみを返すことができます。例:
// Piece::returnPiece is a function taking no arguments and returning a pointer to a
// 4x4 array of integers
int (*Piece::returnPiece(void))[4][4]
{
// return pointer to the array
return &pieceArray;
}
使用するには、次のように呼び出します:
int (*arrayPtr)[4][4] = myPiece->returnPiece();
int cell = (*arrayPtr)[i][j]; // cell now stores the contents of the (i,j)th element
型宣言とそれを使用することの類似性に注意してください-括弧、逆参照演算子 *
、および括弧は同じ場所にあります。
Grid :: InsertArray
の宣言は正しいです。引数は1つで、整数の4x4配列です。これは値渡しです:呼び出すたびに4x4配列のコピーを作成するため、変更は渡された配列に反映されません。代わりに参照渡しを使用する場合は、代わりにポインタを配列に渡します:
// InsertArray takes one argument which is a pointer to a 4x4 array of integers
void Grid::InsertArray(int (*arr)[4][4])
{
for(int i = 0; i < x_ROWS; i++)
{
for(int j = 0; j < y_COLUMNS ; j++)
squares[i][j] = (*arr)[i][j];
}
}
多次元配列へのポインターを使用したこれらの型宣言は、非常に紛らわしくなります。次のように typedef
を作成することをお勧めします。
// Declare IntArray4x4Ptr to be a pointer to a 4x4 array of ints
typedef int (*IntArray4x4Ptr)[4][4];
その後、より読みやすい関数を宣言できます:
IntArray4x4Ptr Piece::returnPiece(void) { ... }
void Grid::InsertArray(IntArray4x4Ptr arr) { ... }
cdecl プログラムを使用して支援することもできます。複雑なC / C ++型を解読します。
他のヒント
C ++のポインターと、参照渡しと値渡しの両方について詳しく読む必要があるようです。
returnPieceメソッドは、単一のセルの値を返すように定義されています。インデックス([4] [4]など)を指定すると、そのセルの内容のコピーが返されるので、変更することはできません。より正確には、変更するとコピーが変更されます。
誰かが正しい構文を教えてくれると確信していますが、間違ったコードを使用する可能性があるので、このことを学ぶことをお勧めします。
ここに私がそれをする方法があります:
class Array { public: Array() { for (int i = 0; i < 4; ++i) { for (int j = 0; j < 4; ++j) { (*this)(i, j) = 0; } } } int &operator()(int i, int j) { return pieceArray[i][j]; } private: int pieceArray[4][4]; };
次のようなことができます:
Array x; // create 4x4 array x(1, 2) = 3; // modify element
Aem Rosenfieldの問題 arrayPtr の問題は、 Piece :: pieceArray があなたの下から変更できることです。 (参照によるコピーと値によるコピー)。
値によるコピーは非効率的です。しかし、本当にやりたい場合は、カンニングするだけです:
struct FOO { int piece [4][4]; };
FOO Piece::returnPiece()
{
FOO f;
memcpy( f.piece, pieceArray, sizeof(pieceArray) );
return f;
}
void Grid::InsertArray( const FOO & theFoo )
{
// use theFoo.piece[i][j]
}
もちろん、より良い、よりオブジェクト指向のソリューションは、 returnPiece()に Piece または Array を作成させて返すことです。オブジェクト。 ( Juan が提案したように...)