What Is Useful About a Reference-To-Array Parameter

What is useful about a reference-to-array parameter?

The reference-to-array parameter does not allow array type to decay to pointer type. i.e. the exact array type remains preserved inside the function. (For example, you can use the sizeof arr / sizeof *arr trick on the parameter and get the element count). The compiler will also perform type checking in order to make sure the array argument type is exactly the same as the array parameter type, i.e. if the parameter is declared as a array of 10 ints, the argument is required to be an array of exactly 10 ints and nothing else.

In fact, in situations when the array size is fixed at compile-time, using a reference-to-array (or pointer-to-array) parameter declarations can be preceived as the primary, preferred way to pass an array. The other variant (when the array type is allowed to decay to pointer type) are reserved for situations when it is necessary to pass arrays of run-time size.

For example, the correct way to pass an array of compile-time size to a function is

void foo(int (&arr)[10]); // reference to an array

or

void foo(int (*arr)[10]); // pointer to an array

An arguably incorrect way would be to use a "decayed" approach

void foo(int arr[]); // pointer to an element
// Bad practice!!!

The "decayed" approach should be normally reserved for arrays of run-time size and is normally accompanied by the actual size of the array in a separate parameter

void foo(int arr[], unsigned n); // pointer to an element
// Passing a run-time sized array

In other words, there's really no "why" question when it comes to reference-to-array (or pointer-to-array) passing. You are supposed to use this method naturally, by default, whenever you can, if the array size is fixed at compile-time. The "why" question should really arise when you use the "decayed" method of array passing. The "decayed" method is only supposed to be used as a specialized trick for passing arrays of run-time size.

The above is basically a direct consequence of a more generic principle. When you have a "heavy" object of type T, you normally pass it either by pointer T * or by reference T &. Arrays are no exception from this general principle. They have no reason to be.

Keep in mind though that in practice it is often makes sense to write functions that work with arrays of run-time size, especially when it comes to generic, library-level functions. Such functions are more versatile. That means that often there's a good reason to use the "decayed" approach in real life code, Nevertheless, this does not excuse the author of the code from recognizing the situations when the array size is known at compile time and using the reference-to-array method accordingly.

C++ pass an array by reference

Arrays can only be passed by reference, actually:

void foo(double (&bar)[10])
{
}

This prevents you from doing things like:

double arr[20];
foo(arr); // won't compile

To be able to pass an arbitrary size array to foo, make it a template and capture the size of the array at compile time:

template<typename T, size_t N>
void foo(T (&bar)[N])
{
// use N here
}

You should seriously consider using std::vector, or if you have a compiler that supports c++11, std::array.

C++ Pass a reference to an array to function

There are many different options here depending on what you want to do here.

If you have a raw array of byte objects, you can pass it into a function like this:

void hello(byte arr[]) {
// Do something with arr
}

int main() {
byte arr[4];
hello(arr);
}

The mechanism by which the array is passed into the function (a pointer to the first element of the array is passed to the function) functions similarly to pass-by-reference: any changes you make to arr in hello will stick in main even though you didn't explicitly pass in a reference to it. However, the hello function won't check whether the array has size four or not - it'll take in as input an array of any number of bytes.

You can also write

void hello(byte (&arr)[4]) {
// ...
}

int main() {
byte arr[4];
hello(arr);
}

The syntax byte (&arr)[4] means "a reference to an array of four bytes." This explicitly passes the array by reference into hello, and it will check the size of the array to make sure it's correct. However, this is very unusual syntax and rarely seen in practice.

But perhaps the best idea is to not use raw arrays and to use std::array instead:

void hello(std::array<byte, 4>& arr) {
// Do something with arr
}

int main() {
std::array<byte, 4> arr;
hello(arr);
}

Now, there's no weirdnesses about strange parentheses in the syntax for arrays of bytes and there's no worries about size checking. Everything is handled properly because std::array is an object type that has all the advantages of regular object types. I'd recommend going with this last approach above all the other ones.

Whats the difference between reference to an array and array as a parameters in functions?

You can specify a complete array type parameter as for example

void f( int ( &a )[N] );

and within the function you will know the number of elements in the passed array.

When the function is declared like

void f( int a[] );

then the compiler adjusts the function declaration like

void f( int *a );

and you are unable to determine the number of elements in the passed array. So you need to specify a second parameter like

void f( int *a, size_t n );

Also functions with a referenced array parameter type may be overloaded. For example these two declarations

void f( int ( &a )[] );

and

void f( int ( &a )[2] );

declare two different functions.

And functions with a referenced array parameter type may be called with a braced list (provided that the corresponding parameter has the qualifier const) like for example

f( { 1, 2, 3 } );

Here is a demonstration program

#include <iostream>

void f( const int ( &a )[] )
{
std::cout << "void f( const int ( & )[] ) called.\n";
}

void f( const int ( &a )[2] )
{
std::cout << "void f( const int ( & )[2] ) called.\n";
}

void f( const int a[] )
{
std::cout << "void f( const int [] ) called.\n";
}

int main()
{
f( { 1, 2, 3 } );
}

The program output is

void f( const int ( & )[] ) called.

Difference between passing an array by value and reference in C++

The first one decays to a pointer to the first element in the array, the second is an actual reference to the array.

They're different in the same way that pointers and references are generally different.

Specifically, in the case of arrays, a reference to the array is useful because you retain the ability to determine the size of the array. This frees you from having to pass the size/length of the array as a separate parameter as you would in a C API.

One way of implementing this that I think is particularly slick involves templates. Using a template parameter, you can get the compiler to automatically deduce the size of the array. For example:

void ProcessArray(int* pArray, std::size length)
{
for (std::size_t i = 0; i < length; ++i)
{
// do something with each element in array
}
}

template <std::size_t N>
void ProcessArray(int (&array)[N])
{
ProcessArray(array, N); // (dispatch to non-template function)
}

Pass Array by Reference in C

Arrays are always passed by reference in C. The name of the array is pointer to the first element of it. So, you just do this :-

void function (int arr[]){
// Some Code.....
}
int main(){
// Some Code...
int name[5];
function(name);
// Some Code...
}

And that would work, you can modify the values of elements in the array and the changes would be reflected in the calling function.

Edit: You know that you have to add a semi-colon after your for loop? Otherwise the next one line will also be iterated. See -

Corrected Code
and
Output



Related Topics



Leave a reply



Submit