Подтвердить что ты не робот

Как передать массив в конструктор?

Я хочу передать массив конструктору, но передается только первое значение - остальное выглядит как мусор.

Вот упрощенная версия того, над чем я работаю:

#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 пробела для кода? Это довольно утомительно.)

4b9b3361

Ответ 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();
    };