web-dev-qa-db-ja.com

配列をコンストラクタに渡すにはどうすればよいですか?

配列をコンストラクタに渡したいのですが、最初の値しか渡されません。残りはゴミのように見えます。

これが私が取り組んでいることの簡単なバージョンです:

#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つのスペースでインデントする必要がありますか?それはかなり退屈です。)

16
Svad Histhana

この場合、配列への参照を使用するのが最善です。

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オブジェクトを初期化する配列は、少なくともオブジェクトと、オブジェクトの外部の配列に加えられた変更がオブジェクトの状態に「反映」される限り存続する必要があることです。ただし、これらの欠点は、元の配列へのポインターを使用した場合にも発生します(基本的に、配列をコピーするだけでこれらの欠点が解消されます)。

もう1つの欠点は、配列要素へのポインターを使用してオブジェクトを作成できないできないことです(これは、配列関数パラメーターが配列サイズはパラメーターの宣言では提供されません)。たとえば、配列が実際にはポインターである関数パラメーターを介して渡され、その関数がその配列を参照するboardオブジェクトを作成できるようにしたい場合などです。

10
Michael Burr

配列を関数に渡そうとすると、配列の最初の要素にポインターが渡されます。

配列を割り当てることはできません。また、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;
}
5
Seth Carnegie
#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();
    };
1

*state = *arr;は、ポインターのアドレスにある値を返す逆参照を使用しています。

state[0] = *arr;intであるため、これは*arrと同じです。

ポインタについての情報は この記事 を参照してください。参照セクションを参照してください。

この問題を解決するには、次のようにします。

for (int i = 0; i < 64; i++) state[i] = arr[i]
0
Avi

配列の名前は、その最初の要素のアドレスです。

したがって、*state = *arrという行はstate[0]arr[0]に設定します。

現在、stateint state[64];として定義しているため、stateは、アドレスを変更できないintタイプのconst pointerです。

これをint *state;に変更すると、state = arrが機能します。

0
vvnraman

* arrは、arr [0]に格納されている値を示します。 c ++では、配列の名前は配列の最初の要素へのポインターです。

したがって、* state = * arrを実行すると、arr [0]の値が変数stateに格納されます。

ここで、各要素を明示的にコピーせずに配列を渡す場合は、呼び出すメソッドで同じサイズの別の配列を作成し、基本的に呼び出し元から配列の名前を渡すことをお勧めします。

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
}
0
angryInsomniac