配列をコンストラクタに渡したいのですが、最初の値しか渡されません。残りはゴミのように見えます。
これが私が取り組んでいることの簡単なバージョンです:
#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つのスペースでインデントする必要がありますか?それはかなり退屈です。)
この場合、配列への参照を使用するのが最善です。
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
オブジェクトを作成できるようにしたい場合などです。
配列を関数に渡そうとすると、配列の最初の要素にポインターが渡されます。
配列を割り当てることはできません。また、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;
}
#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();
};
*state = *arr;
は、ポインターのアドレスにある値を返す逆参照を使用しています。
state[0] = *arr;
はint
であるため、これは*arr
と同じです。
ポインタについての情報は この記事 を参照してください。参照セクションを参照してください。
この問題を解決するには、次のようにします。
for (int i = 0; i < 64; i++) state[i] = arr[i]
配列の名前は、その最初の要素のアドレスです。
したがって、*state = *arr
という行はstate[0]
をarr[0]
に設定します。
現在、state
をint state[64];
として定義しているため、state
は、アドレスを変更できないint
タイプのconst pointer
です。
これをint *state;
に変更すると、state = arr
が機能します。
* 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
}