5

We've been learning about reference parameters in my Intro to Programming class. I understand perfectly that reference parameters give you access to the place where an argument is held in memory, while value parameters create copies of the arguments.

Why would I want my function to have access to the argument's memory location instead of its value?

  • 3
    Have you considered asking your instructor about it? Such a question would be much better suited to a discussion environment such as a class - especially when it would help you work through the path the instructor is trying to set forth. Asking us could lead you on wild tangents that would hinder you from learning the material necessary to get through the class. – user40980 Mar 8 '16 at 19:24
  • 3
    One reason is simply to avoid copying an entire source object, especially if it's large (in this case you usually want to use a reference to const). The other obvious reason is if code in the function might need to modify the original object (in which case you want a non-const reference). – Jerry Coffin Mar 8 '16 at 19:32
  • 4
    Incidentally, that's not accurate. Pointers are the ones that give you the memory location. References also allow you to refer to a value, but without exposing its memory location (it's often helpful to think of references as a safer, highly-restricted version of pointers). – Ixrec Mar 8 '16 at 19:38
  • There are often times when you want only one copy of the value in memory, and you want multiple methods to work on that value. Another use I've seen is if you want a method to return multiple values, and do not want to create a separate class to hold all these values. – Rachel Mar 10 '16 at 20:55
13

There are a few reasons this may be useful.

Non-copyable types

Not everything can be passed by value! std::unique_ptr, for example, may only be moved, not copied, because it makes no sense to copy something that has unique ownership over a resource. Its copy constructor has been "deleted", which means passing it by value into any function will simply fail.

Large types

Maybe your function only needs to inspect the object's current value, without actually changing it. If the object is large, copying it is pointless and wasteful. Not only are you taking up more memory and CPU cycles than you need, but if you have a deep recursion, yes you may indeed contribute to the likelihood of a stack overflow because your stack frames are much larger than they need to be.

Typically, in these scenarios, we'll pass by const reference to avoid accidental mutations.

Mutation

Maybe the object is being passed in as an "out" parameter, so that the changes made inside the function are to be visible at the call site. Here's an example:

bool foo(std::string& a)
{
    const char* result = someSysCall("...");
    if (result) {
       a = result;
       return true;
    }
    else {
       return false;
    }
}

int main()
{
    std::string str;
    if (foo(str)) {
       // do things with str
    }
    else {
       // show an error?
    }
}

While oftentimes we'd use exceptions instead of this pattern, out parameters are still widespread in many libraries (particularly the Windows API). They are often implemented using pointers instead, but the principle is exactly the same.

3

C gets by with having values and pointers. C++ adds references.

A lot of this is to support operator overloading. For example, let's assume you want to overload operator -- or operator = for some particular type. Both of these (and quite a few more besides) need to modify the object they receive as a parameter.

Now, in C when you need to have a function modify something, you pass a pointer to that something. When you're dealing with an overloaded operator, however, you don't really have that option. If you have code like ++foo; or foo -= bar;, you don't have any real way to specify that for this case, I want to pass the address of foo instead of its value. To pass the address, you need to take the address at the call site, so you end up with things like

scanf("%d", &destination);

References allow you to achieve roughly the same result, but the syntax to do so is entirely in the called function rather than at the call site, so a normal expression with normal syntax can still pass a reference so the called function can modify its parameter.

Although there certainly are other perfectly valid uses for references in C++, and using them can be (often is) cleaner and safe than using a pointer, most other cases could be done using a pointer if references weren't available. This case pretty much requires a reference--it simply won't work with a pointer.

  • Might be worth mentioning that it doesn't work with pointers because &foo++ already has another meaning: It does pointer arithmetic. And the syntax would be really ugly, too. – 5gon12eder Mar 17 '16 at 19:32
  • An advantage of references over pointers is that if a compiler sees someOutsideFunction(&someLocalVariable); it will often have to pessimistically assume that that function might have stored a copy of the pointer it received somewhere the compiler it doesn't know about (allowing, e.g., any other outside functions that are called during the lifetime of that variable to modify it). Passing a reference avoids that problem, since the address of the reference isn't guaranteed to remain valid after the return from the function to which it was given. – supercat Dec 8 '16 at 21:06
  • @supercat: yeah--there are actually quite a few advantages. I intended, however, to concentrate on something that went beyond advantage, and was a matter of truly needing something different from pointers (at least as they exist in C) to support the feature at all (and I think operator overloading qualifies). – Jerry Coffin Dec 8 '16 at 21:11
  • @supercat. If you pass an object by reference, the called function can take the address of the reference, which is a pointer to the original, and store it in a static or global variable. It’s slightly more naughty than storing a pointer that was passed, but equally valid C++. – gnasher729 Jan 5 at 16:15
  • @gnasher729: A language which is trying to be serious about optimization should provide a means of passing things by reference without authorizing the called function to persist the reference in question someplace that will be used after the function has returned. Requiring that functions which are going to persist addresses accept pointers rather than references would be a minor semantic limitation compared with other restrictions that are imposed for "optimization". – supercat Jan 5 at 21:19
-5

Ah! Something just came to mind - recursion. If a recursive function needs access to a variable, and you want the function to pass that variable to itself, then you want - and may need - a reference parameter. Otherwise, you're just allocating unnecessary memory - and may, in fact, cause a "stack overflow".

Edit: Some people have noted that pointers exist. Be that as it may, reference variables are sometimes preferable simply because they render referencing and dereferencing unnecessary.

  • Not sure why this was downvoted. It's correct. – Lightness Races with Monica Mar 10 '16 at 22:34
  • 1
    Sort of - reference params aren't a guaranteed cure for stack overflow (since the stack frame itself likely has some size). Didn't downvote, though. – Useless Mar 11 '16 at 13:54
  • 1
    @BarryTheHatchet I didn't downvote, but the problem with this answer is that it is an incomplete answer which only states one minor reason while there are many more major reasons. Also I have seen and implemented many recursive functions which use and in fact require call-by-value and return-by-value. – Philipp Mar 11 '16 at 14:19
  • 1
    I didn't downvote it, but I'd hazard a guess that it's largely because it doesn't show why you need references vs. pointers (which C already had). – Jerry Coffin Mar 17 '16 at 15:54
  • The question doesn't mention pointers once and has nothing to do with pointers. It clearly positions itself as a question about references vs values. – Lightness Races with Monica Jan 5 at 14:09

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.