[c++] What does '&' do in a C++ declaration?

I am a C guy and I'm trying to understand some C++ code. I have the following function declaration:

int foo(const string &myname) {
  cout << "called foo for: " << myname << endl;
  return 0;
}

How does the function signature differ from the equivalent C:

int foo(const char *myname)

Is there a difference between using string *myname vs string &myname? What is the difference between & in C++ and * in C to indicate pointers?

Similarly:

const string &GetMethodName() { ... }

What is the & doing here? Is there some website that explains how & is used differently in C vs C++?

This question is related to c++ syntax operators

The answer is


The "&" denotes a reference instead of a pointer to an object (In your case a constant reference).

The advantage of having a function such as

foo(string const& myname) 

over

foo(string const* myname)

is that in the former case you are guaranteed that myname is non-null, since C++ does not allow NULL references. Since you are passing by reference, the object is not copied, just like if you were passing a pointer.

Your second example:

const string &GetMethodName() { ... }

Would allow you to return a constant reference to, for example, a member variable. This is useful if you do not wish a copy to be returned, and again be guaranteed that the value returned is non-null. As an example, the following allows you direct, read-only access:

class A
{
  public:
  int bar() const {return someValue;}
  //Big, expensive to copy class
}

class B
{
public:
 A const& getA() { return mA;}
private:
 A mA;
}
void someFunction()
{
 B b = B();
 //Access A, ability to call const functions on A
 //No need to check for null, since reference is guaranteed to be valid.
 int value = b.getA().bar(); 
}

You have to of course be careful to not return invalid references. Compilers will happily compile the following (depending on your warning level and how you treat warnings)

int const& foo() 
{
 int a;

 //This is very bad, returning reference to something on the stack. This will
 //crash at runtime.
 return a; 
}

Basically, it is your responsibility to ensure that whatever you are returning a reference to is actually valid.


string * and string& differ in a couple of ways. First of all, the pointer points to the address location of the data. The reference points to the data. If you had the following function:

int foo(string *param1);

You would have to check in the function declaration to make sure that param1 pointed to a valid location. Comparatively:

int foo(string &param1);

Here, it is the caller's responsibility to make sure the pointed to data is valid. You can't pass a "NULL" value, for example, int he second function above.

With regards to your second question, about the method return values being a reference, consider the following three functions:

string &foo();
string *foo();
string foo();

In the first case, you would be returning a reference to the data. If your function declaration looked like this:

string &foo()
{
    string localString = "Hello!";
    return localString;
}

You would probably get some compiler errors, since you are returning a reference to a string that was initialized in the stack for that function. On the function return, that data location is no longer valid. Typically, you would want to return a reference to a class member or something like that.

The second function above returns a pointer in actual memory, so it would stay the same. You would have to check for NULL-pointers, though.

Finally, in the third case, the data returned would be copied into the return value for the caller. So if your function was like this:

string foo()
{
    string localString = "Hello!";
    return localString;
}

You'd be okay, since the string "Hello" would be copied into the return value for that function, accessible in the caller's memory space.


Your function declares a constant reference to a string:

int foo(const string &myname) {
  cout << "called foo for: " << myname << endl;
  return 0;
}

A reference has some special properties, which make it a safer alternative to pointers in many ways:

  • it can never be NULL
  • it must always be initialised
  • it cannot be changed to refer to a different variable once set
  • it can be used in exactly the same way as the variable to which it refers (which means you do not need to deference it like a pointer)

How does the function signature differ from the equivalent C:

int foo(const char *myname)

There are several differences, since the first refers directly to an object, while const char* must be dereferenced to point to the data.

Is there a difference between using string *myname vs string &myname?

The main difference when dealing with parameters is that you do not need to dereference &myname. A simpler example is:

int add_ptr(int *x, int* y)
{
    return *x + *y;
}
int add_ref(int &x, int &y)
{
    return x + y;
}

which do exactly the same thing. The only difference in this case is that you do not need to dereference x and y as they refer directly to the variables passed in.

const string &GetMethodName() { ... }

What is the & doing here? Is there some website that explains how & is used differently in C vs C++?

This returns a constant reference to a string. So the caller gets to access the returned variable directly, but only in a read-only sense. This is sometimes used to return string data members without allocating extra memory.

There are some subtleties with references - have a look at the C++ FAQ on References for some more details.


Here, & is not used as an operator. As part of function or variable declarations, & denotes a reference. The C++ FAQ Lite has a pretty nifty chapter on references.


One way to look at the & (reference) operator in c++ is that is merely a syntactic sugar to a pointer. For example, the following are roughly equivalent:

void foo(int &x)
{
    x = x + 1;
}

void foo(int *x)
{
    *x = *x + 1;
}

The more useful is when you're dealing with a class, so that your methods turn from x->bar() to x.bar().

The reason I said roughly is that using references imposes additional compile-time restrictions on what you can do with the reference, in order to protect you from some of the problems caused when dealing with pointers. For instance, you can't accidentally change the pointer, or use the pointer in any way other than to reference the singular object you've been passed.


In this context & is causing the function to take stringname by reference. The difference between references and pointers is:

  • When you take a reference to a variable, that reference is the variable you referenced. You don't need to dereference it or anything, working with the reference is sematically equal to working with the referenced variable itself.
  • NULL is not a valid value to a reference and will result in a compiler error. So generally, if you want to use an output parameter (or a pointer/reference in general) in a C++ function, and passing a null value to that parameter should be allowed, then use a pointer (or smart pointer, preferably). If passing a null value makes no sense for that function, use a reference.
  • You cannot 're-seat' a reference. While the value of a pointer can be changed to point at something else, a reference has no similar functionality. Once you take a variable by reference, you are effectively dealing with that variable directly. Just like you can't change the value of a by writing b = 4;. A reference's value is the value of whatever it referenced.

#include<iostream>
using namespace std;
int add(int &number);

int main ()
{
            int number;
            int result;
            number=5;
            cout << "The value of the variable number before calling the function : " << number << endl;
            result=add(&number);
            cout << "The value of the variable number after the function is returned : " << number << endl;
            cout << "The value of result : " << result << endl;
            return(0);
}

int add(int &p)
{
            *p=*p+100;
            return(*p);
}

This is invalid code on several counts. Running it through g++ gives:

crap.cpp: In function ‘int main()’:
crap.cpp:11: error: invalid initialization of non-const reference of type ‘int&’ from a temporary of type ‘int*’
crap.cpp:3: error: in passing argument 1 of ‘int add(int&)’
crap.cpp: In function ‘int add(int&)’:
crap.cpp:19: error: invalid type argument of ‘unary *’
crap.cpp:19: error: invalid type argument of ‘unary *’
crap.cpp:20: error: invalid type argument of ‘unary *’

A valid version of the code reads:

#include<iostream>
using namespace std;
int add(int &number);

int main ()
{
            int number;
            int result;
            number=5;
            cout << "The value of the variable number before calling the function : " << number << endl;
            result=add(number);
            cout << "The value of the variable number after the function is returned : " << number << endl;
            cout << "The value of result : " << result << endl;
            return(0);
}

int add(int &p)
{
            p=p+100;
            return p;
}

What is happening here is that you are passing a variable "as is" to your function. This is roughly equivalent to:

int add(int *p)
{
      *p=*p+100;
      return *p;
}

However, passing a reference to a function ensures that you cannot do things like pointer arithmetic with the reference. For example:

int add(int &p)
{
            *p=*p+100;
            return p;
}

is invalid.

If you must use a pointer to a reference, that has to be done explicitly:

int add(int &p)
{
                    int* i = &p;
            i=i+100L;
            return *i;
}

Which on a test run gives (as expected) junk output:

The value of the variable number before calling the function : 5
The value of the variable number after the function is returned : 5
The value of result : 1399090792

Examples related to c++

Method Call Chaining; returning a pointer vs a reference? How can I tell if an algorithm is efficient? Difference between opening a file in binary vs text How can compare-and-swap be used for a wait-free mutual exclusion for any shared data structure? Install Qt on Ubuntu #include errors detected in vscode Cannot open include file: 'stdio.h' - Visual Studio Community 2017 - C++ Error How to fix the error "Windows SDK version 8.1" was not found? Visual Studio 2017 errors on standard headers How do I check if a Key is pressed on C++

Examples related to syntax

What is the 'open' keyword in Swift? Check if returned value is not null and if so assign it, in one line, with one method call Inline for loop What does %>% function mean in R? R - " missing value where TRUE/FALSE needed " Printing variables in Python 3.4 How to replace multiple patterns at once with sed? What's the meaning of "=>" (an arrow formed from equals & greater than) in JavaScript? How can I fix MySQL error #1064? What do >> and << mean in Python?

Examples related to operators

What is the difference between i = i + 1 and i += 1 in a 'for' loop? Using OR operator in a jquery if statement What is <=> (the 'Spaceship' Operator) in PHP 7? What does question mark and dot operator ?. mean in C# 6.0? Boolean operators ( &&, -a, ||, -o ) in Bash PowerShell and the -contains operator How do I print the percent sign(%) in c Using the && operator in an if statement What do these operators mean (** , ^ , %, //)? How to check if div element is empty