C++ Возврат и вставка объекта двумерного массива
Вопрос
Я пытаюсь вернуть элемент данных массива из одного меньшего объекта 2D-массива и пытаюсь вставить массив в более крупный объект 2D-массива.Но пытаясь это сделать, я столкнулся с двумя проблемами.
Первая проблема заключается в том, что я хочу вернуть имя 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]; }
Но я не уверен, хочу ли я этого, поскольку хочу вернуть массив и все его содержимое.
Другая проблема — это функция InsertArray(), где я бы поместил функцию returnPiece() в аргумент InsertArray().
Проблема с 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(), и если я удалю «[4][4]», мой компилятор не примет.
В основном все это синтаксические ошибки, но как мне решить эти проблемы?
- Возврат всего массива PieceArray в returnPiece()
- Правильный синтаксис аргумента в InsertArray().
- Аргумент InsertArray(), принимающий returnPiece().
Эти три основные проблемы, с которыми мне нужна помощь, и у меня возникла та же проблема, когда я пытался использовать метод указателя указателя.Кто-нибудь знает, как решить эти 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
правильно - он принимает один аргумент, который представляет собой массив целых чисел 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
Проблема с Адам Розенфилд массивПтр в этом Часть::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() создать и вернуть Кусок или Множество объект.(Как Хуан предложенный...)