What I want to do is something like this:
void dosth(bool& a) {
a[2] = false;
}
int main() {
bool a[10];
dosth(a);
return 0;
}
I want to call by reference, with an array as argument. How to realize this?
Thx
What I want to do is something like this:
void dosth(bool& a) {
a[2] = false;
}
int main() {
bool a[10];
dosth(a);
return 0;
}
I want to call by reference, with an array as argument. How to realize this?
Thx
You have to declare the argument as a pointer:
void dosth(bool* a) {
a[2] = false;
}
An array is essentially the same as a pointer
You can allow the array to decay to a pointer, as in Philippe's answer. A more type-safe solution, that only accepts arrays and allows compile-time range checks, is
template <size_t SIZE>
void dosth(bool (&a)[SIZE])
{
a[2] = false;
}
You could add static_assert(SIZE > 2);
(or BOOST_STATIC_ASSERT(SIZE > 2);
if your compiler doesn't support static_assert
) to give a compile error if the index would be out of range.
Like this:
typedef bool array_type[10];
void dosth(array_type& a)
{
a[2] = false;
}
int main()
{
array_type a;
dosth(a);
}
Or without the typedef:
void dosth(bool (&a)[10])
{
a[2] = false;
}
int main()
{
bool a[10];
dosth(a);
}
Or more generally:
template <size_t Size>
void dosth(bool (&a)[Size])
{
/*static_*/assert(Size > 2);
a[2] = false;
}
int main()
{
bool a[10];
dosth(a);
}
If you're not in C++0x, you can implement a (simple) static_assert
like this:
template <bool>
struct static_assert_type;
template <> // only true is defined
struct static_assert_type<true> {}
#define static_assert(x) { static_assert_type<(x)>(); }
Which allows you uncomment the static_assert
and get a compile-time error if the array size is too small.
If you want a reference to an array you can do the following. Note that then dosth
will only accept reference to arrays of that size, and that you will not be able to give a heap allocated array (ie bool* c = new bool[10]
).
void dosth(bool (&a)[10]) {
a[2] = false;
}
int main() {
bool a[10];
bool (&aa)[10] = a;
dosth(a);
return 0;
}
This is kind of tricky, the simple way (and the only available in C) is defining the signature of the function as taking a pointer:
void dosth( bool* a );
The array will automatically decay into a pointer to the first element and it will work as long as you are careful enough. Note that void dosth( bool a[10] )
is exactly the above signature: the compiler will translate that for you.
This is not safe for a couple of reasons, first is that it allows callers to pass an array of any size, or even no array at all (dosth(0);
).
That can be made typesafe in C++ by using a reference:
void dosth( bool (&a)[ 10 ] );
Now, the compiler will ensure that an array of exactly 10 bools is passed into the function. There are a couple of implications there, the first of all is that not only the user cannot pass a null pointer, but she is restricted to passing an array of exactly 10 elements, so you need not worry about overflow when accessing the third element later on (a[2]=false;
).
On the other hand, it limits usability, as users cannot pass an array of more than 10 elements, nor a dynamically allocated array (new bool[10]
). That can be improved by using a template:
template <std::size_t N>
void dosth( bool (&a)[N] ) {
static_assert( N >= 10 );
//...
}
EDIT: I was going to respond to Cedric with a comment, but it would probably be too long. You are right in that it leaves the dynamically allocated problem unresolved. As @GMan says, in the general case you want to use other data types that will take care of the dynamically allocated memory. Anyway, there is a complex way of getting this to work with memory allocated with new[]
, it is just not so direct.
The problem is that the type must be bool [10]
, but new T[n]
returns a T*
and not a T[n]
. Providing a typedef does not help either:
typedef bool b10[10];
b10* p = new b10; // error cannot convert from int* to int (*)[10]
You can overcome that limitation by not requesting a single array but an array of arrays:
bool (*array)[10] = new bool[1][10];
dosth(*array);
But of course you will need to use delete []
and not plain delete
:
delete [] array;