1

If I have a function that takes a reference to a map:

pair<int,int> myFunc(map<int,char> &myVar){...}

I can pass it a map without needing the '&'.

myFunc(someMapitoa);

Is there any difference? Is a copy made and then thrown away? Should I use the '&' anyway?

fightermagethief
  • 322
  • 1
  • 2
  • 14
  • 1
    No a copy is not made. It is passed by reference. Using '&' when calling myFunc would take the address of the field and cause a compile error. – GreatAndPowerfulOz Oct 27 '15 at 19:16
  • 1
    What is "implied"? You explicitly state that the parameter is by reference. – Neil Kirk Oct 27 '15 at 19:19
  • The `&` in the function declaration indicates that the variable in question is a [reference](http://en.cppreference.com/w/cpp/language/reference_initialization), whereas the `&` elsewhere is the [`address-of` operator](https://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&cad=rja&uact=8&ved=0CB0QFjAAahUKEwjIka2Zr-PIAhUGaD4KHbWjCts&url=https%3A%2F%2Fmsdn.microsoft.com%2Fen-us%2Flibrary%2F64sa8b1e.aspx&usg=AFQjCNHtYjVhhfSqTvIOqKLfmC_VV7hAhw). Don't conflate the two. – R_Kapp Oct 27 '15 at 19:20
  • @NeilKirk One can see it as 'implied' at the call site. But, I agree. In C++ it's explicit with the function definition. – GreatAndPowerfulOz Oct 27 '15 at 19:20

2 Answers2

5

C++ is pass-by-value by default.

So, this makes a copy:

void foo (bar b);

This does not:

void foo (bar & b);

This makes a copy of a pointer, but not the actual data that it points to:

void foo (bar * b);

If you really want to get deeper into it then see this SO post about move semantics.

Anyway, for the above three examples they are all called the same way:

#include <iostream>
using namespace std;

int alpha (int arg) {
    // we can do anything with arg and it won't impact my caller
    // because arg is just a copy of what my caller passed me
    arg = arg + 1;
    return arg;
}

int bravo (int & arg) {
    // if I do anything to arg it'll change the value that my caller passed in
    arg = arg + 1;
    return arg;
}

int charlie (int * arg) {
    // when we deal with it like this it's pretty much the same thing
    // as a reference even though it's not exactly the same thing
    *arg = *arg + 1;
    return *arg;
}

int main () {
    int a = 0;

    // 1
    cout << alpha (a) << endl;
    // 1
    cout << bravo (a) << endl;
    // 2
    cout << charlie (&a) << endl;

    return 0;
}
Community
  • 1
  • 1
erapert
  • 1,383
  • 11
  • 15
2

You should think of this in terms of what is being initialized from what.

When you call a function, each argument is used to initialize the corresponding parameter. If the parameter is declared with reference type, it's a reference. If the parameter is not declared with reference type, it's an object.

  • The initialization of a reference to class type T from an expression of type T never makes a copy.
  • The initialization of an object of class type T from an expression of type T either copies or moves.

The rules here are the same as the rules for initializing non-parameter variables, as in:

T t = ...
T& r = ...

The fact that a function may take a reference to an argument even when there is no explicit notation at the call site is viewed by some as confusing. This is why some style guides ban non-const reference parameters (such as the Google C++ style guide) and force you to declare the argument as a pointer so that & must be used at the call site. I don't advocate this coding style, but it is an option you might want to consider.

Brian Bi
  • 111,498
  • 10
  • 176
  • 312