Tutorial :Passing array by ref



Question:

Ref. to my last post and sellibitze's comment to that post on passing array by ref rather than by value, why is it that when I'm passing array by value compiler can deduce arguments but it won't do it if I pass it by value?

template<class T,int row, int col>  void invert(T (&a)[row][col]) //NOTE AMPERSAND  

in main with declaration above I can call:

int main(int argc, char* argv[])  {  invert(a);//HERE ARGUMETS ARE AUTOMATICALLY DEDUCED  }  

but without ampersand I would have to call it like so:

 int main(int argc, char* argv[])      {      invert<int,3,4>(a);      }  

@Paul So just to make it clear when I'm declaring fnc:

void f(int a[]);//I'm passing a pointer  

but when I'm declaring:

void f(int &a[]);//I'm passing a ref?  

Do I understand this correctly now?


Solution:1

That's because when you pass an array "by value" it decays to a pointer. That is, you are in fact passing a pointer to the first element without any size information.

When you have a signature like this:

 void foo(int arr[10]);  

then the value 10 is completely ignored and you can pass arrays of ints of any size to it. It is exactly the same as

 void foo(int arr[]);  

or

void foo(int* arr);  

As you can see the size information is not preserved, and therefore it cannot be used to deduce the size of the array.

With a two-dimensional array, the first dimension decays. For example: an array of 10 arrays of 20 integers (int arr[10][20]) decays to a pointer to arrays of 20 integers (int (*arr)[20]) etc, so the value 10 cannot be deduced but the size of the second dimension (20) is preserved an can be deduced.

template<class T,int row, int col>  void foo(T (&a)[row][col]) { }    template <class T, int col>  void bar(T arr[][col]) {}    int main()  {      int a[10][20];      foo(a);      bar(a);  }  

When you pass something by reference, the type is preserved, the arrays don't decay and all the size information will remain available.


Solution:2

You can't pass array by value, only by pointer (when you pass an array to a function it's automatically converted to a pointer).

I don't really understand what you mean by "deduce arguments"; do you mean the total size of the array? If yes then if you pass it by pointer it's lost because pointers don't carry that kind of information.

Anyways I highly recommend to use std::vector rather than plain old C arrays; many less headaches! They are passed by value by default (as you would expect); they can easily passed by reference and by pointer if you want to, and they never lose information such as the array size. They also protected against buffer overflows and underflows, and they automatically grow as you add more elements.


Solution:3

void f(int &a[]); // I'm passing a ref?  

No, here you try to pass an array of references, which does not exist in the type system. You might be tempted to write the following:

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

But references to arrays of unknown bound are not allowed as function parameters.


When you declare a function parameter as an array of n dimensions, it is rewritten by the compiler as a pointer to an array of n-1 dimensions. The following signatures are equivalent:

void fun(int x[][10]);  void fun(int x[2][10]);  void fun(int x[99][10]);  void fun(int (*x)[10]);  

The bound of the first dimension is ignored and thus cannot be inferred by the template mechanism.

What you can do is pass a pointer to the entire 2D array:

template <class T, int row, int col>  void invert(T (*a)[row][col])  {      std::cout << row << " x " << col << std::endl;      T first_entry = (*a)[0][0];  }    int main(int argc, char* argv[])  {      int a[10][20];      invert(&a);  }  

This works as expected, but as you can see, the syntax is a little clumsy on both sides.


Note:If u also have question or solution just comment us below or mail us on toontricks1994@gmail.com
Previous
Next Post »