Reference and value parameters

In a void function, if a parameter is passed by reference, that value shares the same memory location as the actual value. Is it safe for me to assume that I should only associate a reference parameter with a void function if I want to change the value of a parameter? Do these mean the same thing? If I use a reference parameter in a value returning function, what happens?
1
2
3
4
5
6
7
8
9
void getScore(int& score)
{
  //statements
}

int getScore(int score)
{
    //statements
}

What difference does it make? If your function is intended to change the value of one object you should return it just to make it clear that you are returning the change. I generally send parameters by reference *anyway* and unless you have a reason to pass by the value itself, copying it, then you'd be better off with a reference.
Theoretically though the effect would be the same, if I understand you correctly... a rather strange question to ask.
I just found this, from now on I will finish the chapter before asking questions, thanks for your input tummychow.
"You can use reference parameters in a value returning function, although this approach is not recommended. By definition, a value returning function returns a single value; this value is returned via the return statement. If a function needs to return more than one value, you should change it to a void function and use the appropriate reference parameters to return the values." C++ Programming - D.S. Malik
What difference does it make?
Quite a lot.

If your function is intended to change the value of one object you should return it just to make it clear that you are returning the change.
Yes! Nothing like making unnecessary copies of objects!

I generally send parameters by reference *anyway* and unless you have a reason to pass by the value itself, copying it, then you'd be better off with a reference.
Yes! Indirection for primitives instead of copy! That's the way to go!
oh, helios XD

Anyway....

- passing by value makes a copy.
- passing by reference involves an indirection.

Both have tradeoffs. Whether or not passing by value is "worth it" depends on a number of things. Including how expensive a copy is, how often the variable is used in the function, and how the compiler decides to compile the code.

Generally (and these are very general rules):

1) Large objects or classes should be passed by reference. The rationale is that larger objects will be more expensive to copy.

2) Classes that have no/few public data members (but have public member functions) should be passed by reference. The rationale is that member functions require an indirection ANYWAY (for the this pointer), and so there's no point in creating the copy since it doesn't spare you any indirection.

3) Small primitive types should be passed by value. The rationale is that making a copy of an int is as inexpensive as it gets. Passing an int by reference makes a copy of the pointer to the int (just as slow or slower than copying the int), AND you get indirection on top of that.

4) When passing by reference, pass by const reference to make it clear the object will not be changed. Only pass by nonconst reference if the function is expected to change the passed parameter. This is a clarity thing and it makes your code much easier to follow.

*) Note that if the function is inlined and/or very small, the compiler might be able to optimize out the copy/indirection anyway.

----------------------

Now that all of that is out of the way... as for the original example -- prefer the getScore that returns an int. The reasons for this:

It lets you compound the statement easier. IE: you can pass getScore as a parameter, or use it in a computation without having to use a temp variable:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// if it returns, you can do things like this:
setHighScore( getScore() );

int nextmilestone = getScore() + 1000;

//------------------
// if it's passed by ref, you have to make temp vars:

int temp;
getScore(temp);
setHighScore(temp);  // 3 lines vs 1, additional variable

int nextmilestone;
getScore(nextmilestone);
nextmilestone += 1000;  // 3 lines instead of 1, not as clear 

Last edited on
Awesome explanation thank you, and shallow copying large amounts of data sounds logical to me, unless you really need two copies. Passing by const reference? That rasies more questions, what happens if I reference a return value? Is it possible to have a const return type as well?

i.e.
1
2
3
4
5
6
int example(int& num1, int num2)
{
    static int num3 = num2;
    num1 = num1 * num2;
    return &num2;
}

Passing by const reference? That rasies more questions


For primitive types like int it doesn't make sense to do so, but say you have a complex class:

1
2
3
4
5
6
7
8
9
void func1(const MyClass& a)  // pass by const reference
{
  // 'a' can be used in this funciton, but cannot be modified
}

void func2(MyClass& a)  // pass by nonconst reference
{
  // 'a' can be used and modified by this function
}


Unless the goal of the function is to modify the parameter, then use a const reference. A function that takes a nonconst reference is a clear indicator that the parameter is an "out" parameter (or an "in/out" parameter).

This is a segway into a whole thing about const correctness though. Being const correct with your class writing is a little tricky, but should be learned right away because it can be very difficult to make an existing class const correct if it isn't. But const correctness is another topic. Maybe I'll write an article on it.

what happens if I reference a return value?


Not sure I get what you're asking.

Functions can return a reference (const or nonconst) just like any other type. The trick is to make sure what you're referring to doesn't go out of scope when the function exits.

Example:

1
2
3
4
5
6
7
8
9
10
11
int& func()
{
  int explode = 9;
  return explode;
}

int main()
{
  int& foo = func();
  foo = 7;  //EXPLODE
}


'func' returns a reference to the local 'explode' variable. The problem is, as soon as the function exits, 'explode' loses scope and dies. Therefore you're effectively returning a bad reference (bad pointer) ie: heap corruption (the worst of the worst types of bugs).

So only return a reference to something that has a longer lifetime. Probably the most common instance of this is a class's member function returning a reference to one of its members:

1
2
3
4
5
6
7
8
9
10
11
12
13
class MyClass
{
  int member;

public:
  int& func() { return member; }
};

int main()
{
  MyClass a;
  a.func() = 5;  // OK
}


Is it possible to have a const return type as well?


Yes. A const value doesn't make much sense to return, though. But a const reference is quite common.

ie: const int foo(); doesn't make a lot of sense, but const int& foo(); does.


As for your example code -- line 5 is wrong =P. The return type is int and you're returning int*. I'm not sure what you were trying to illustrate there, either.
Last edited on
Topic archived. No new replies allowed.