问题
I want to pass an array to a constructor, but only the first value is passed--the rest looks like garbage.
Here's a simplified version of what I'm working on:
#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;
}
Can someone explain why this doesn't work and how to properly pass an array? Also, I don't want to copy the array. (And do I really have to indent every line by 4 spaces for code? That's pretty tedious.)
回答1:
In this case it might be best to use a reference to the array:
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();
};
A couple of advantages - no copying of the array, and the compiler will enforce that the correct size array is passed in.
The drawbacks are that the array you initialize the board object with needs to live at least as long as the object and any changes made to the array outside of the object are 'reflected' into the object's state. but those drawbacks occur if you use a pointer to the original array as well (basically, only copying the array will eliminate those drawbacks).
One additional drawback is that you can't create the object using a pointer to an array element (which is what array function parameters 'decay' to if the array size isn't provided in the parameter's declaration). For example, if the array is passed through a function parameter that's really a pointer, and you want that function to be able to create a board object referring to that array.
回答2:
Attempting to pass an array to a function results in passing a pointer to the first element of the array.
You can't assign arrays, and taking a parameter like T[] is the same as T*. So
*state = *arr;
Is dereferencing the pointers to state and arr and assigning the first element of arr to the first element of state.
If what you want to do is copy the values from one array to another, you can use std::copy:
std::copy(arr, arr + 64, state); // this assumes that the array size will
// ALWAYS be 64
Alternatively, you should look at std::array<int>, which behaves exactly like you were assuming arrays behave:
#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:
#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;
}
or you can use it as:
class board
{
public:
int state[64];
board(int arr[])
{
for(int i=0;i<64;++i)
state[i] = arr[i];
}
void print();
};
EDIT 1: stable solution
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();
};
回答4:
*arr gives the value that is stored at arr[0] . In c++ , the name of the array is a pointer to the first element in the array.
So when you do *state = *arr , you store the value at arr[0] in the variable state.
Now , if you want to pass the array without having to copy each element explicitly , I suggest that you make another array of the same size in the method which you are calling and then pass the name of the array from the caller , in essence :
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
}
回答5:
The name of an array is the address of the first element in it.
Hence the line *state = *arr will set state[0] to arr[0].
Since right now you have defined state as int state[64];, state is const pointer of type int whose address cannot be changed.
You can change it to int *state; and then state = arr will work.
回答6:
*state = *arr; is using dereferencing, which returns the value at the address of the pointer.
This is the same as state[0] = *arr; because *arr is an int.
See this article for info on pointers. See the deference section.
To solve this problem you want to do this:
for (int i = 0; i < 64; i++) state[i] = arr[i]
来源:https://stackoverflow.com/questions/9426932/how-do-i-pass-an-array-to-a-constructor