Showing posts with label Pass By Reference. Show all posts
Showing posts with label Pass By Reference. Show all posts

Matrix in Functions

In this tutorial from our C++ ebook, we will learn how to work with matrix and functions, learning to declare, invoke and use these two important topics together.

How to Pass a Matrix to a Function

In the study of arrays, we saw that there are some ways to declare the header of functions with arrays as parameters, as follows:
  • type func(tipo *array);
  • type func(tipo array[tamanho]);
  • type func(tipo array[]);

In other words, just pass the pointer (*array - we will study more ahead) or just with the pair of open brackets (array[]).

In the case of two-dimensional arrays, we need to specify the number of columns in the array we are sending:
  • void func(int arr[][COLUMN]);

You see, the number of rows is not mandatory (we can even pass), but the number of columns is.
Let's declare and initialize a 2x2 matrix and then send it to the show() function, which will simply display it as a table, see how our code looks:
#include <iostream>
using namespace std;

void show(int arr[][2], int row)
{
    for (int i=0 ; i<row ; i++){
        for(int j=0 ; j<2 ; j++)
            cout<<arr[i][j]<<"  ";
        cout<<endl;
    }
}

int main()
{
    int arr[][2]={ {1,2}, {3,4} };
    show(arr, 2);
    return 0;
}
Look some important things in the code above.

First, we pass the array arr[][2] to the function, with the number of columns.
But what about the number of lines? How will the function know how many lines to print the table?
It doesn't know, so we pass another parameter in the function, the integer 'row'.

C++ Matrix: Passing by Reference

All data passing to functions that involve arrays and matrix is by reference. Ever.
That is, passed an array to a function? It will directly access the array and its data, directly into memory. It is not a copy that goes to function, it is not a pass for value, ok?

That means one thing: watch out! Functions can modify the arrays, always remember that.
The code below introduces the 'init' function, which will receive an array and initialize each element of it, asking the user:
#include <iostream>
using namespace std;
const int COLS = 3;
const int ROWS = 3;

void init(int arr[][COLS], int ROWS)
{
    for(int i=0 ; i<ROWS ; i++)
        for(int j=0 ; j<COLS ; j++){
            cout << "matrix["<<i+1<<"]["<<j+1<<"]: ";
            cin  >> arr[i][j];
        }
}

void show(int arr[][COLS], int ROWS)
{
    for (int i=0 ; i<ROWS ; i++){
        for(int j=0 ; j<COLS ; j++)
            cout<<arr[i][j]<<"  ";
        cout<<endl;
    }
}

int main()
{
    int arr[ROWS][COLS];
    init(arr, ROWS);
    show(arr, ROWS);
    return 0;
}
To improve the organization, we have already defined the rows (ROWS) and columns (ROLS) as global variables of the constant type, so that there is no danger of anyone, anywhere in the code, changing their values. This makes the code clearer and safer for maintenance.

Array of arrays in C++

Matrix Exercise in C ++

Create a 4x4 matrix, where each row represents a student's grades, and each column is a different subject. You must create a function that will fill in the students' grades, one by one, indicating which is the subject and which is the student.

Then, your program should display, in an organized manner, the grades of each student, as well as the average of each, the class average for each subject, and the general average, of all students of all grades.

Post your solution in the comments.

Arrays in Functions

In this tutorial from our C++ Arrays section, we will learn how to work with arrays and functions, learning how to pass an array as an argument, how to return and receive an array, how to copy, compare and change arrays using functions.

Arrays as arguments to Functions

What basically differentiates an integer variable from an array of integers? Let's see the statements:
  • int num;
  • int num[2112];

Well, it's the pair of square brackets, with a number inside. Do you agree?
When we pass an integer to a function, its prototype is:
  • show(int num); or show(int);

So, as you might suspect, to pass an array as an argument, you can do, in the prototype:
  • show(int num[]); or show(int []);

You see, you only pass with the pair of brackets, okay? No number inside.
In the function code, the header is with: show (int num[]);

Let's give a code example of an array that we declared in main(), of integers, we pass to the show() function and it displays these elements.
Look at how we invoke the function: show (num);

The name of the array is 'num', okay? Do not: show(num[]) to invoke the function.
#include <iostream>
using namespace std;

void show(int []);

int main()
{
    int num[]={10, 20, 30};

    show(num);

    return 0;
}

void show(int num[])
{
    int count;

    for(count=0 ; count<3 ; count++)
        cout<<"Elements "<<count+1<<": "<<num[count]<<endl;
}
Got it? However, there is a problem ... the function 'already knew' beforehand that the array had 3 elements. But, well, the functions don't have a crystal ball. Therefore, it is common and usual, to pass along with the array, its size too, for the functions:
#include <iostream>
using namespace std;

void show(int [], int);

int main()
{
    int num[]={10, 20, 30, 40, 50};
    int size=5;
    show(num, size);

    return 0;
}

void show(int num[], int size)
{
    int count;

    for(count=0 ; count<size ; count++)
        cout<<"Elements "<<count+1<<": "<<num[count]<<endl;
}

When we study the vector class, in STL, we will see more dynamic and powerful types of arrays, and we will not have to worry about informing the size of the array, as it will be information specific to the structure we are going to use.

Return Array: Pass by reference

Let's create an array called num[], insert some numbers.
Next, let's move on to the doub() function, which will double each element of the array, and print it doubled.

Then, we print, now in main(), again the array num:
#include <iostream>
using namespace std;

void doub(int [], int);

int main()
{
    int num[]={10, 20, 30, 40, 50};
    int size=5, count;

    doub(num, size);

    for(count=0 ; count<size ; count++)
        cout<<num[count]<<"  ";

    return 0;
}

void doub(int num[], int size)
{
    int count;

    for(count=0 ; count<size ; count++)
        num[count] *= 2;

    for(count=0 ; count<size ; count++)
        cout<<num[count]<<"  ";

    cout<<endl;
}
The result is:
20  40  60  80  100
20  40  60  80  100

Now, look at that! You passed an array to the function. Inside it, it doubled.
When you returned from the function, to main(), and you printed the array again, it was doubled.
In other words: the function changed the array.

Although you only passed the name of the array, it changed the original array. That is: when we pass an array to a function, this pass is by reference. When we pass the array name to the function, C++ passes the actual address of the array. Thus, the function changes that memory position, directly, and not a copy of the value (as it happens when passing by value).

This is for efficiency reasons, since it would take a long time to make a copy of the arrays passed to the functions (on a day-to-day basis, we work with very large arrays).

OK? C++ passes the array by reference, don't forget!

How to copy Arrays

Often, we want to do some things with arrays, but without changing them.
For example, suppose we have 'num' array of integers, and we want another array where each element is triple the value of each element of the 'num' array.

What we can do is first create a copy of 'num', let's call it 'copy', and bang, we send 'copy' to a function that triples the elements. As the passage is by reference, it will change the values of the 'copy' and will not even know about the existence of 'num', which is unchanged.

To make a 'copyArray' function that makes a copy of an array, we need to pass both arrays as an argument to the function, as well as their size, which must be necessarily the same. Then, just copy element by element, with a loop.

See how our code looks:
#include <iostream>
using namespace std;

void copyArray(int [], int [], int);
void triple(int [], int);

int main()
{
    int num[]={10, 20, 30, 40, 50}, copy[5];
    int size=5, count;

    copyArray(num, copy, size);
    triple(copy, size);

    cout<<"Original Array: "<<endl;
    for(count=0 ; count<size ; count++)
        cout<<num[count]<<"  ";

    cout<<"\nTriplicate Array: "<<endl;
    for(count=0 ; count<size ; count++)
        cout<<copy[count]<<"  ";

    return 0;
}

void copyArray(int num[], int copy[], int size)
{
    int count;

    for(count=0 ; count<size ; count++)
        copy[count] = num[count];
}

void triple(int copy[], int size)
{
    int count;

    for(count=0 ; count<size ; count++)
        copy[count] *= 3;

}
Result:
Original Array:
10 20 30 40 50

Tripled Array:
30 60 90 120 150

If you really want to preserve the original 'num' array and really want to make sure it doesn't change, you can declare it and use it as const:

  • In the header: void copyArray(const int [], int [], int);
  • In the function declaration: void copyArray(const int num [], int copy [], int size) {...}
  • In array declaration: const int num [] = {10, 20, 30, 40, 50};

Reference Parameters and Variables

In this tutorial of our C++ course, we will learn how to pass arguments by reference into functions.

Pass by Value

We have already learned how to send information to functions through arguments and parameters.
And we saw that this pass is called pass by value, because we only pass the value to the function.

If we send a variable to a function, and within that function that variable is changed, it is not changed outside the function. Test the following code, which squares a number:
#include <iostream>
using namespace std;

void square(int num);

int main()
{
    int number = 6;

    cout<<"Before  : num = "<<number<<endl;
    square(number);
    cout<<"After   : num = "<<number<<endl;

    return 0;
}

void square(int num)
{
    num = num*num;
    cout<<"During  : num = "<<num<<endl;
}
When we invoke the function: square (number), we are actually passing a copy of the value of the variable number.

Within the function, the num variable will receive a copy of the value of number. That is, it will not have access to the original variable number, only its value! Therefore, passing by value.

Reference Parameter: &

Be the variable declaration:
  • int num = 6;

What we are doing is allocating, reserving, a space in the memory of your computer.

So when we use num, C++ understands that we must go to the address this variable points to and get the number inside that memory location.

As we have seen, when we pass this normal variable to a function that expects a normal variable, it takes only a copy of its value, and does not mess with the original content.

However, there is another special type of variable, the reference variable.

It is special because if we pass a variable to a function and the function wants to get the reference variable through a reference parameter, it will have access to the memory address (the reference) where this variable is originally stored.

That is: we will actually have access to the variable, not just its copy.

To get the reference of a variable, just use the & operator before the variable name, in the function parameter! It is the reference parameter. Both in the prototype and in the function declaration.

So the previous code example looks like this:
#include <iostream>
using namespace std;

void square(int &);

int main()
{
    int number = 6;

    cout<<"Before  : num = "<<number<<endl;
    square(number);
    cout<<"After   : num = "<<number<<endl;

    return 0;
}

void square(int &num)
{
    num = num*num;
    cout<<"During  : num = "<<num<<endl;
}
See now the result:
Parameter reference

In fact, the function was able to change the value of the variable because this argument pass to the parameter was by reference parameter.

What happens here is that the parameter will not capture the value of the argument but its reference to where it is pointing in memory. Speaking of pointing to an address, we will study more about it in the pointers and arrays (vectors) sections in C++, where we will study about passing by reference using pointers.

More about C++ Reference Parameters

Some programmers also prefer to declare the prototype like this:
  • square (int&);

You can also use it like this in the prototype:
  • square(int &num);
  • square(int& num);

Also, the important thing is that & is in both the prototype and function declaration, ok?

Remember that if your parameter is reference, it can only work with reference variable.
It would be a mistake if you use an argument that is not a variable, such as a literal, an expression, or a constant, for example:
  • square(10); // must use square (number);
  • square(number+1); // it's an expression, avoid
When we do: square (int &num)

Read: "num is a reference to an integer", that is, it is referencing, pointing, indicating a memory location where an integer is stored. Since you have the location of the original variable, you can change this value.

Value passing and reference exercise

Create a program that prompts the user for an integer. Then it must turn this value into its cube. Do this by using a function that receives pass by value and another that uses parameter and reference variable. Make it clear that one changes the value only within the function (value) and the other changes the original value of the variable (reference).

Paste in the comments, your solution.