Как передать массив в конструктор?
Я хочу передать массив конструктору, но передается только первое значение - остальное выглядит как мусор.
Вот упрощенная версия того, над чем я работаю:
#include <iostream>
class board
{
public:
int state[64];
board(int arr[])
{
*state = *arr;
}
void print();
};
void board::print()
{
for (int y=0; y<8; y++)
{
for (int x=0; x<8; x++)
std::cout << state[x + y*8] << " ";
std::cout << "\n";
}
}
int main()
{
int test[64] = {
0, 1, 2, 3, 4, 5, 6, 7,
1, 2, 3, 4, 5, 6, 7, 8,
2, 3, 4, 5, 6, 7, 8, 9,
3, 4, 5, 6, 7, 8, 9,10,
4, 5, 6, 7, 8, 9,10,11,
5, 6, 7, 8, 9,10,11,12,
6, 7, 8, 9,10,11,12,13,
7, 8, 9,10,11,12,13,14 };
board b(test);
b.print();
std::cin.get();
return 0;
}
Может кто-нибудь объяснить, почему это не работает и как правильно передать массив? Кроме того, я не хочу копировать массив. (И действительно ли мне нужно отступать каждую строку на 4 пробела для кода? Это довольно утомительно.)
Ответы
Ответ 1
В этом случае лучше всего использовать ссылку на массив:
class board
{
int (&state)[64];
public:
board(int (&arr)[64])
: state(arr)
{}
// initialize use a pointer to an array
board(int (*p)[64])
: state(*p)
{}
void print();
};
Несколько преимуществ - без копирования массива, и компилятор будет обеспечивать, чтобы был принят правильный массив размера.
Недостатки в том, что массив, который вы инициализируете объект board
, должен жить как минимум до тех пор, пока объект и любые изменения, внесенные в массив вне объекта, "отражены" в состоянии объекта. но эти недостатки возникают, если вы используете указатель на исходный массив (в основном, только копирование массива устраняет эти недостатки).
Еще один недостаток заключается в том, что вы не можете создать объект с помощью указателя на элемент массива (который является тем, что параметры функции массива "распадаются", если размер массива не указан в объявлении параметра). Например, если массив передается через параметр функции, который действительно является указателем, и вы хотите, чтобы эта функция могла создать объект board
, относящийся к этому массиву.
Ответ 2
Попытка передать массив функции приводит к передаче указателя на первый элемент массива.
Вы не можете назначать массивы, а параметр типа T[]
совпадает с T*
. Так
*state = *arr;
Разыменовывает указатели на state
и arr
и присваивает первый элемент arr
первому элементу state
.
Если вы хотите скопировать значения из одного массива в другой, вы можете использовать std::copy
:
std::copy(arr, arr + 64, state); // this assumes that the array size will
// ALWAYS be 64
Альтернативно, вы должны посмотреть std::array<int>
, который ведет себя точно так же, как вы предполагали, что массивы ведут себя:
#include <array>
#include <algorithm>
#include <iostream>
class board
{
public:
std::array<int, 64> state;
board(const std::array<int, 64> arr) // or initialiser list : state(arr)
{
state = arr; // we can assign std::arrays
}
void print();
};
void board::print()
{
for (int y=0; y<8; y++)
{
for (int x=0; x<8; x++)
std::cout << state[x + y*8] << " ";
std::cout << "\n";
}
}
int main()
{
// using this array to initialise the std::array 'test' below
int arr[] = {
0, 1, 2, 3, 4, 5, 6, 7,
1, 2, 3, 4, 5, 6, 7, 8,
2, 3, 4, 5, 6, 7, 8, 9,
3, 4, 5, 6, 7, 8, 9,10,
4, 5, 6, 7, 8, 9,10,11,
5, 6, 7, 8, 9,10,11,12,
6, 7, 8, 9,10,11,12,13,
7, 8, 9,10,11,12,13,14 };
std::array<int, 64> test(std::begin(arr), std::end(arr));
board b(test);
b.print();
std::cin.get();
return 0;
}
Ответ 3
*state = *arr;
используется разыменование, которое возвращает значение по адресу указателя.
Это то же самое, что и state[0] = *arr;
, потому что *arr
является int
.
См. эту статью для получения информации о указателях. Смотрите раздел уважения.
Чтобы решить эту проблему, вы хотите сделать это:
for (int i = 0; i < 64; i++) state[i] = arr[i]
Ответ 4
Имя массива - это адрес первого элемента в нем.
Следовательно, строка *state = *arr
установит state[0]
в arr[0]
.
Так как прямо сейчас вы определили state
как int state[64];
, state
is const pointer
типа int
, адрес которого не может быть изменен.
Вы можете изменить его на int *state;
, а затем state = arr
будет работать.
Ответ 5
* arr дает значение, которое хранится в arr [0]. В С++ имя массива является указателем на первый элемент в массиве.
Итак, когда вы делаете * state = * arr, вы сохраняете значение в arr [0] в состоянии переменной.
Теперь, если вы хотите передать массив без необходимости скопировать каждый элемент явно, я предлагаю вам сделать другой массив того же размера в методе, который вы вызываете, а затем передать имя массива из вызывающего, по существу:
methodWhereArrayisPassed(int *arrayName)
{
int arrCopy[64];
arrCopy = arrayName;
// Do more stuff here
}
methodWhichPassesArray()
{
// do stuff here
int arr[] = {
0, 1, 2, 3, 4, 5, 6, 7,
1, 2, 3, 4, 5, 6, 7, 8,
2, 3, 4, 5, 6, 7, 8, 9,
3, 4, 5, 6, 7, 8, 9,10,
4, 5, 6, 7, 8, 9,10,11,
5, 6, 7, 8, 9,10,11,12,
6, 7, 8, 9,10,11,12,13,
7, 8, 9,10,11,12,13,14 };
methodWhereArrayisPassed(arr);
// do stuff here
}
Ответ 6
#include <iostream>
class board
{
public:
int * state; //changed here, you can also use **state
board(int *arr) //changed here
{
state = arr;
}
void print();
};
void board::print()
{
for (int y=0; y<8; y++)
{
for (int x=0; x<8; x++)
std::cout << *(state + x + y*8) << " "; //changed here
std::cout << "\n";
}
}
int main()
{
int test[64] = {
0, 1, 2, 3, 4, 5, 6, 7,
1, 2, 3, 4, 5, 6, 7, 8,
2, 3, 4, 5, 6, 7, 8, 9,
3, 4, 5, 6, 7, 8, 9,10,
4, 5, 6, 7, 8, 9,10,11,
5, 6, 7, 8, 9,10,11,12,
6, 7, 8, 9,10,11,12,13,
7, 8, 9,10,11,12,13,14 };
board b(test);
b.print();
std::cin.get();
return 0;
}
или вы можете использовать его как:
class board
{
public:
int state[64];
board(int arr[])
{
for(int i=0;i<64;++i)
state[i] = arr[i];
}
void print();
};
ИЗМЕНИТЬ 1:
устойчивое решение
class board
{
public:
int * state; //changed here, you can also use **state
board(int *arr) //changed here
{
state = new int[64];
for(int i=0;i<64;++i)
state[i] = arr[i];
}
void print();
};