How to Use Reference Parameters in C++

Passing by reference in C

Because you're passing the value of the pointer to the method and then dereferencing it to get the integer that is pointed to.

C intro - How to pass a parameter by reference in function?

  1. It is perfectly valid. You can initialize and pass any number of pointer variables with their reference.

  2. This is also valid..when you pass the variable address, you should store it into a pointers

you have to do some changes in your code,
You can assign directly a/b and a*b pointer variables *c & *d
Then you have to read double number with %lf format argument.

#include <stdio.h>
#include <string.h>

void myFunction(double a, double b, double *c, double *d)
{
*c = a/b; //change
*d = a*b; //change
printf("%lf %lf",*c,*d);
return;
//printf statements
}



int main()
{
//first and second double hold the scanf inputs
double first;
double second;

//unsure here - to reference c and d as parameters in the function, do I simply declare unfilled double variables here?
double *c;
double *d;

printf("Enter your first number\n");
scanf("%lf", &first); //change
printf("Enter your second number\n");
scanf("%lf", &second); //change

//call the function, first and second by value, &c / &d by reference - correct?
myFunction(first, second, &c,&d);
}

How do I use Reference Parameters in C++?

Think of a reference as an alias. When you invoke something on a reference, you're really invoking it on the object to which the reference refers.

int i;
int& j = i; // j is an alias to i

j = 5; // same as i = 5

When it comes to functions, consider:

void foo(int i)
{
i = 5;
}

Above, int i is a value and the argument passed is passed by value. That means if we say:

int x = 2;
foo(x);

i will be a copy of x. Thus setting i to 5 has no effect on x, because it's the copy of x being changed. However, if we make i a reference:

void foo(int& i) // i is an alias for a variable
{
i = 5;
}

Then saying foo(x) no longer makes a copy of x; i is x. So if we say foo(x), inside the function i = 5; is exactly the same as x = 5;, and x changes.

Hopefully that clarifies a bit.


Why is this important? When you program, you never want to copy and paste code. You want to make a function that does one task and it does it well. Whenever that task needs to be performed, you use that function.

So let's say we want to swap two variables. That looks something like this:

int x, y;

// swap:
int temp = x; // store the value of x
x = y; // make x equal to y
y = temp; // make y equal to the old value of x

Okay, great. We want to make this a function, because: swap(x, y); is much easier to read. So, let's try this:

void swap(int x, int y)
{
int temp = x;
x = y;
y = temp;
}

This won't work! The problem is that this is swapping copies of two variables. That is:

int a, b;
swap(a, b); // hm, x and y are copies of a and b...a and b remain unchanged

In C, where references do not exist, the solution was to pass the address of these variables; that is, use pointers*:

void swap(int* x, int* y)
{
int temp = *x;
*x = *y;
*y = temp;
}

int a, b;
swap(&a, &b);

This works well. However, it's a bit clumsy to use, and actually a bit unsafe. swap(nullptr, nullptr), swaps two nothings and dereferences null pointers...undefined behavior! Fixable with some checks:

void swap(int* x, int* y)
{
if (x == nullptr || y == nullptr)
return; // one is null; this is a meaningless operation

int temp = *x;
*x = *y;
*y = temp;
}

But looks how clumsy our code has gotten. C++ introduces references to solve this problem. If we can just alias a variable, we get the code we were looking for:

void swap(int& x, int& y)
{
int temp = x;
x = y;
y = temp;
}

int a, b;
swap(a, b); // inside, x and y are really a and b

Both easy to use, and safe. (We can't accidentally pass in a null, there are no null references.) This works because the swap happening inside the function is really happening on the variables being aliased outside the function.

(Note, never write a swap function. :) One already exists in the header <algorithm>, and it's templated to work with any type.)


Another use is to remove that copy that happens when you call a function. Consider we have a data type that's very big. Copying this object takes a lot of time, and we'd like to avoid that:

struct big_data
{ char data[9999999]; }; // big!

void do_something(big_data data);

big_data d;
do_something(d); // ouch, making a copy of all that data :<

However, all we really need is an alias to the variable, so let's indicate that. (Again, back in C we'd pass the address of our big data type, solving the copying problem but introducing clumsiness.):

void do_something(big_data& data);

big_data d;
do_something(d); // no copies at all! data aliases d within the function

This is why you'll hear it said you should pass things by reference all the time, unless they are primitive types. (Because internally passing an alias is probably done with a pointer, like in C. For small objects it's just faster to make the copy then worry about pointers.)

Keep in mind you should be const-correct. This means if your function doesn't modify the parameter, mark it as const. If do_something above only looked at but didn't change data, we'd mark it as const:

void do_something(const big_data& data); // alias a big_data, and don't change it

We avoid the copy and we say "hey, we won't be modifying this." This has other side effects (with things like temporary variables), but you shouldn't worry about that now.

In contrast, our swap function cannot be const, because we are indeed modifying the aliases.

Hope this clarifies some more.


*Rough pointers tutorial:

A pointer is a variable that holds the address of another variable. For example:

int i; // normal int

int* p; // points to an integer (is not an integer!)
p = &i; // &i means "address of i". p is pointing to i

*p = 2; // *p means "dereference p". that is, this goes to the int
// pointed to by p (i), and sets it to 2.

So, if you've seen the pointer-version swap function, we pass the address of the variables we want to swap, and then we do the swap, dereferencing to get and set values.

Does C even have pass by reference ?

C parameters are always passed by value rather than by reference. However, if you think of the address of an object as being a reference to that object then you can pass that reference by value. For example:

void foo(int *x)
{
*x = 666;
}

You ask in a comment:

So why do we need pointers in C when we can pass all the parameters by value?

Because in a language that only supports pass-by-value, lack of pointers would be limiting. It would mean that you could not write a function like this:

void swap(int *a, int *b)
{
int temp = *a;
*b = *a;
*a = temp;
}

In Java for example, it is not possible to write that function because it only has pass-by-value and has no pointers.

In C++ you would write the function using references like this:

void swap(int &a, int &b)
{
int temp = a;
b = a;
a = temp;
}

And similarly in C#:

void swap(ref int a, ref int b)
{
int temp = a;
b = a;
a = temp;
}

Meaning of pass by reference in C and C++?

In colloquial usage, "pass by reference" means that, if the callee modifies its arguments, it affects the caller, because the argument as seen by the callee refers to the value as seen by the caller.

The phrase is used independent of the actual programming language, and how it calls things (pointers, references, whatever).

In C++, call-by-reference can be done with references or pointers. In C, call-by-reference can only be achieved by passing a pointer.

"Call by value":

void foo( int x )
{
// x is a *copy* of whatever argument foo() was called with
x = 42;
}

int main()
{
int a = 0;
foo( a );
// at this point, a == 0
}

"Call by reference", C style:

void foo( int * x )
{
// x is still a *copy* of foo()'s argument, but that copy *refers* to
// the value as seen by the caller
*x = 42;
}

int main()
{
int a = 0;
foo( &a );
// at this point, a == 42
}

So, strictly speaking, there is no pass-by-reference in C. You either pass the variable by-value, or you pass a pointer to that variable by-value.

C++: Argument Passing passed by reference

The ability to pass by reference exists for two reasons:

  1. To modify the value of the function arguments
  2. To avoid make copies of an object for performance reasons

Example for modifying the argument

void get5and6(int *f, int *s)  // using pointers
{
*f = 5;
*s = 6;
}

this can be used as:

int f = 0, s = 0;
get5and6(&f,&s); // f & s will now be 5 & 6

OR

void get5and6(int &f, int &s)  // using references
{
f = 5;
s = 6;
}

this can be used as:

int f = 0, s = 0;
get5and6(f,s); // f & s will now be 5 & 6

When we pass by reference, we pass the address of the variable. Passing by reference is similar to passing a pointer - only the address is passed in both cases.

For eg:

void SaveGame(GameState& gameState)
{
gameState.update();
gameState.saveToFile("save.sav");
}

GameState gs;
SaveGame(gs)

OR

void SaveGame(GameState* gameState)
{
gameState->update();
gameState->saveToFile("save.sav");
}

GameState gs;
SaveGame(&gs);


Since only the address is being passed, the value of the variable (which could be really huge for huge objects) doesn't need to be copied. So passing by reference improves performance especially when:

  1. The object passed to the function is huge (I would use the pointer variant here so that the caller knows the function might modify the value of the variable)
  2. The function could be called many times (eg. in a loop)

Also, read on const references. When it's used, the argument cannot be modified in the function.

Pass by reference through multiple functions

Just use:

bar(x, y, z);

X, Y, and Z are already pointers - just pass them directly.

Remember - a pointer is a location in memory. The location doesn't change. When you dereference the pointer (using *x = ...), you are setting the value at that location. But when you pass it into a function, you are just passing the location in memory. You can pass that same location into another function, and it works fine.

Pass by reference method

If you want to pass the reference to a function in c, you have to use pointers.
Use the '&' keyword to reference the address of the value. Remember to have a memory location at moment to pass the reference, so you have to store the 'i+2' in local function and pass the reference to your function. Then use '*' to access the value.

#include <stdio.h>  

int twinp(int * n)
{
int i=2;
for (i=2; i<= *n/2; i++)
{
if (*n%i == 0)
return 0;
}
if (i > *n / 2)
return 1;
}

int main ()
{
int i, c= 0;
printf("Twin prime numbers before 100 are: ");
for (i = 2; i <= 100; i++)
{
int i_plus_2 = i+2;
if (twinp(&i) && twinp(&i_plus_2))
{
printf ("(%d, %d) ", i, i+2);
c++;
}
}
printf (" \nTotal number of twin prime pairs: %d\n", c); return 0;
}


Related Topics



Leave a reply



Submit