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

2

7

What is the difference between functions, which have reference to an array:

// reference to array
void f_(char (&t)[5]) {
    auto t2 = t;
}

and simply array:

// just array
void f__(char t[5]) {
    auto t2 = t;
}

as a parameters?

The calling code is:

char cArray[] = "TEST";
f_(cArray);
f__(cArray);

char (&rcArr)[5] = cArray;
f_(rcArr);
f__(rcArr);

In both cases t2 is char*, but in first function my VS2019 is showing that t inside function has type char(&t)[] and t inside second function has type char*.

So after all, is there any practical difference between those functions?

Galitea answered 17/12, 2021 at 18:4 Comment(6)
Try to pass an array as argument to both your functions, and see the first one fail. (The second actually takes a pointer, not an array.)Israelitish
I edited the question. Functions take exact sized arrays.Galitea
The second still takes a pointer; when there's no reference, the size is ignored.Israelitish
The second does not, in fact, take an exact sized array. It takes a pointer. Try it!Tiger
This doesn't address the question, but names that contain two consecutive underscores (f__) and names that begin with an underscore followed by a capital letter are reserved for use by the implementation. Don't use them in your code.Tiger
Two circumstances where you'll see a distinct difference between your functions. (1) Try to pass an array of three char to both. (2) Pass a char * (not an array) to both. In both these circumstances, the calling code will compile in one case and not with the other. Another difference is to print sizeof(t) in both your functions - you'll see (assuming you pass an array of five char to call both) that they produce different output.Despoliation
S
2

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.
Syndicate answered 17/12, 2021 at 18:36 Comment(8)
thanks, but first example wont compile. you need to specify size_t parameter like that: template<size_t N> void f(int (&a)[N]) {};Galitea
@Galitea I did not mean a template function. I mean non-tempalte functions. N is some constant expression or an absence of it.Syndicate
yes, i mean non-template function too, but it wont compile until you specify NGalitea
@Galitea It seems you are using an old compiler or a compiler that contains a bug. See my updated post. You can try the program at www.godbolt.orgSyndicate
then please can you explain how "and within the function you will know the number of elements in the passed array." if i don't specify N ?Galitea
@Galitea If the number of elements in the parameter is specified as for example void f( int ( &a )[10] ); then you will know the number.:) You can apply the operator sizeof to the parameter and you will get the exact size of the array. When the parameter has not a referenced type when even you will specify void f( int a[10] ); the compiler will adjust the function declaration like void f( int *a ); That is you will deal with a pointer.Syndicate
Let us continue this discussion in chat.Galitea
@Galitea I am sorry but I am going to go to bed because in Moscow there is 11.30 p.m.:)Syndicate
C
0

Since you cannot pass arrays by value (a C restriction that C++ inherits) any declaration of a parameter as an array will 'decay' into a pointer (losing its size). So the declaration

void f__(char t[5])

is identical to

void f__(char *t)

Everything else follows from this -- within the body of f__, t has a pointer type, NOT an array type. So any auto inferencing from it will be based on that pointer type.

Calyptra answered 17/12, 2021 at 20:0 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.