9.16 — Reference variables

So far, we’ve discussed two basic variable types:

  • Normal variables, which hold values directly.
  • Pointers, which hold the address of another value (or null) and their value can be retrieved through indirection of address they point to.

References are the third basic type of variable that C++ supports. A reference is a type of C++ variable that acts as an alias to another object or value.

C++ supports three kinds of references:

  1. References to non-const values (typically just called “references”, or “non-const references”), which we’ll discuss in this lesson.
  2. References to const values (often called “const references”), which we’ll discuss in the next lesson.
  3. C++11 added r-value references, which we cover in detail in the chapter on move semantics.

References to non-const values

A reference (to a non-const value) is declared by using an ampersand (&) between the reference type and the variable name:

In this context, the ampersand does not mean “address of”, it means “reference to”.

References to non-const values are often just called “references” for short.

Just like the position of the asterisk of pointers, it doesn’t matter if you place the ampersand at the type or at the variable name.

Best practice

When declaring a reference variable, put the ampersand next to the type to make it easier to distinguish it from the address-of operator.

References as aliases

References generally act identically to the values they’re referencing. In this sense, a reference acts as an alias for the object being referenced. For example:

In the above snippet, setting or getting the value of x, y, or z will all do the same thing (set or get the value of x).

Let’s take a look at references in use:

This code prints:


In the above example, ref and value are treated synonymously.

Using the address-of operator on a reference returns the address of the value being referenced:

Just as you would expect if ref is acting as an alias for the value.

l-values and r-values

In C++, variables are a type of l-value (pronounced ell-value). An l-value is a value that has an address (in memory). Since all variables have addresses, all variables are l-values. The name l-value came about because l-values are the only values that can be on the left side of an assignment statement. When we do an assignment, the left hand side of the assignment operator must be an l-value. Consequently, a statement like 5 = 6; will cause a compile error, because 5 is not an l-value. The value of 5 has no memory, and thus nothing can be assigned to it. 5 means 5, and its value can not be reassigned. When an l-value has a value assigned to it, the current value at that memory address is overwritten.

The opposite of l-values are r-values (pronounced arr-values). An r-value is an expression that is not an l-value. Examples of r-values are literals (such as 5, which evaluates to 5) and non-l-value expressions (such as 2 + x).

Here is an example of some assignment statements, showing how the r-values evaluate:

Let’s take a closer look at the last assignment statement above, since it causes the most confusion.

In this statement, the variable x is being used in two different contexts. On the left side of the assignment operator, “x” is being used as an l-value (variable with an address). On the right side of the assignment operator, x is being used as an r-value, and will be evaluated to produce a value (in this case, 7). When C++ evaluates the above statement, it evaluates as:

Which makes it obvious that C++ will assign the value 8 back into variable x.

The key takeaway is that on the left side of the assignment, you must have something that represents a memory address (such as a variable). Everything on the right side of the assignment will be evaluated to produce a value.

Note: const variables are considered non-modifiable l-values.

References must be initialized

References must be initialized when created:

Unlike pointers, which can hold a null value, there is no such thing as a null reference.

References to non-const values can only be initialized with non-const l-values. They can not be initialized with const l-values or r-values.

Note that in the middle case, you can’t initialize a non-const reference with a const object -- otherwise you’d be able to change the value of the const object through the reference, which would violate the const-ness of the object.

References can not be reassigned

Once initialized, a reference can not be changed to reference another variable. Consider the following snippet:

Note that the second statement may not do what you might expect! Instead of changing ref to reference variable value2, it assigns the value of value2 to value1.

References as function parameters

References are most often used as function parameters. In this context, the reference parameter acts as an alias for the argument, and no copy of the argument is made into the parameter. This can lead to better performance if the argument is large or expensive to copy.

In a previous lesson we talked about how passing a pointer argument to a function allows the function to perform indirection through the pointer to modify the argument’s value directly.

References work similarly in this regard. Because the reference parameter acts as an alias for the argument, a function that uses a reference parameter is able to modify the argument passed in:

This program prints:


When argument n is passed to the function, the function parameter ref is set as a reference to argument n. This allows the function to change the value of n through ref! Note that n does not need to be a reference itself.

Best practice

Pass arguments by non-const reference (rather than by pointer) when the argument needs to be modified by the function.

The primary downside of using non-const references as function parameters is that the argument must be a non-const l-value. This can be restrictive. We’ll talk more about this (and how to get around it) in the next lesson.

Using references to pass C-style arrays to functions

One of the most annoying issues with C-style arrays is that in most cases they decay to pointers when evaluated. However, if a C-style array is passed by reference, this decaying does not happen.

Here’s an example (h/t to reader nascardriver):

Note that in order for this to work, you explicitly need to define the array size in the parameter.

References as shortcuts

A secondary (much less used) use of references is to provide easier access to nested data. Consider the following struct:

Let’s say we needed to work with the value1 field of the Something struct of other. Normally, we’d access that member as other.something.value1. If there are many separate accesses to this member, the code can become messy. References allow you to more easily access the member:

The following two statements are thus identical:

This can help keep your code cleaner and more readable.

References vs pointers

References and pointers have an interesting relationship -- a reference acts like a pointer that implicitly performs indirection through it when accessed (references are usually implemented internally by the compiler using pointers). Thus given the following:

*ptr and ref evaluate identically. As a result, the following two statements produce the same effect:

Because references must be initialized to valid objects (cannot be null) and can not be changed once set, references are generally much safer to use than pointers (since there’s no risk of indirection through a null pointer). However, they are also a bit more limited in functionality accordingly.

If a given task can be solved with either a reference or a pointer, the reference should generally be preferred. Pointers should only be used in situations where references are not sufficient (such as dynamically allocating memory).


References allow us to define aliases to other objects or values. References to non-const values can only be initialized with non-const l-values. References can not be reassigned once initialized.

References are most often used as function parameters when we either want to modify the value of the argument, or when we want to avoid making an expensive copy of the argument.

9.17 -- References and const
9.15 -- Pointers and const

185 comments to 9.16 — Reference variables

  • Alexander Kindel

    Do I understand correctly that the fact that passing a variable to a function by reference doesn't involve copying the variable means passing by reference is always as performant or more performant than passing the variable directly? If so, is there any context where passing a variable directly has an advantage over passing by (constant, where appropriate) reference?

    • Alex

      Passing a variable by reference copies the reference rather than the variable itself. References do have some overhead, so it's not possible to straightforwardly say one way is always better than the other.

      In general, you should pass fundamental variables by value, and complex data types (classes) by reference. This will be the right thing to do most often, and if performance is really a concern in some case, you can profile (time) both methods and compare.

  • Dean

    I was working with problem #2 at the end of Chap 6, and trying to pass a vector of a struct to a function.

    It did not work if I put the & next to the  vector name ie:

    But did work with the & after the vector type in the function call.  ie:

    So what is the difference between the 2?  Thanks.

  • Rohit

    How can we initialize a reference with a const object in the code?

    • Alex

      int main()
      const int cA(16); // this is a const object
      const int &ref = cA; // so we must use a const reference

      std::cout << ref << '\n'; return 0; }

  • Peter

    I used references quite often but I was confused by the the sentence "References are implicitly treated as const."
    I think it would be better to say it from the very beginning that you are talking about constness of the relationship between the reference and the variable that is being referenced.

  • Matthieu B.

    Two lines apart, you write:

    References are implicitly const

    I understand what you mean(the first reference is not a reference to a const object, but it is a const reference - implicitly), but it isn't put very clearly

  • Ajay

    I think const reference name should be "reference to const" same like "pointer to const". What do you think?

    • Alex

      I agree. I've updated the lesson to use the term "reference to const value", since that's what they actually are. But "const reference" is common shorthand for a reference to a const value, so I note that, and will continue to use it throughout the tutorial series.

  • Chris

    Alex, i have a few questions. maybe it is useless, but i just wondering:

    1. is it possible to make reference of built-in fixed array, and built-in dynamic array?(not passing to function)

    2. how to make reference of std::array? i can make for std::vector but i can't with std::array. i try this but it is error:

    3. how to pass built-in dynamic array by reference to function, i had tried many ways with parenthesis but all of them didn't work, i didn't found the way too at google.

    thank you.

    • Alex

      1) Yes.
      2) Your example is causing the compiler to be confused between std::array and variable name array. Try this:


  • Darren

    I think of references as nicknames for variables. They are essentially another name, an alias, for the variable identifier i.e a way to refer to the same object by a different name. For instance, assuming we had a class or type person, then

  • is it not possible in c++ to pass a pointer to function who's argument is a reference for example

  • J3ANP3T3R

    References as shortcuts <-- can this be done by namespace shortcut method ?

  • Shiva


    > Pass non-pointer, non-fundamental data type variables by (const) reference.

    You forgot to prefix it with "Rule: ", Alex. :)

      • Shiva

        Hey Alex,

        I have a query about C: I just found out that references are C++ only, and not supported by C. Do you know whether it was implemented in any later standard of C? If not, pass by (and return by) address is the only work around, isn't it?

        • Alex

          I'm not aware of references being implemented in any standard version of C. So yes, you'd have to use pass by address (which is syntactically ugly and error prone).

        • Shiva

          Right. Thanks for the confirmation. I also checked Balaguruswami's ANSI C - references are not mentioned even in the latest edition.

          I should tell this to my Computer Science teacher, she seems to be unaware of it. :D

  • Karim

    Hey Alex!

    Your guides have been so very helpful man, I've had some programming knowledge but mostly from trial and error, this breaks everything down so neatly that it took me to a whole new level.

    Although, I'd like to see a few things added to this one, such as referencing to a function, for example does

    do the job even if I don't have a variable reference?

    Thank you!

  • psygorkhali

    i am little confused here.

    the  output is 7 7.
    shouldn't it be illegal? value is non-constant and we can change it. but ref is referencing to constant value. then why on changing value, its reflected on ref??

    • Alex

      ref is a reference to value. Think of value as a mailbox. You can open the mailbox and take out what is there and put something else in. Now think of ref as a window on the back of the mailbox. You can use ref to see what's inside the mailbox, but you can't change what's inside through the window.

      However, if you change value, you can look through the window (ref) and see that it has been changed.

  • psygorkhali

        Is "ref" a keyword in c++?? my compiler(code::blocks 13.12) is highlighting it as a keyword but when i use other name it doesn't. if it is a keyword then what is it and what does it do?? ..

    • Alex

      ref isn't a keyword in standard C++, but there is a std::ref class in the standard library. ref _is_ also a keyword in managed C++ (Microsoft's extension to C++). It's likely one of those, but I couldn't say which one.

  • tata

    Hi, an earlier comment above (July 29, 2015 at 10:03 am) corrected the misconception that (L-value) references necessarily occupy storage.

    Could someone confirm that the same does not apply to R-value references?

    I'm a little confused b/c the C++ reference did not distinguish between l-value and r-value references when it stated that: "references are not objects; they do not necessarily occupy storage, although the compiler may allocate storage".


  • Oliver

    Just trying to get my head around this:

    The keyword "const" seems to have different meaning when applied to a pointer as opposed to a reference? Const for the pointer refers to the pointer itself - it cannot be "redirected" to point to a different address. Whereas const for a reference refers to the variable it is referencing - in that it cannot be changed via the reference. Is this correct and am I missing something which is confusing me?

  • Len

    When I read the first few lines of this section I thought, "I can skim this...why would I ever want to create a reference to a variable? Just use the variable".  I am glad I didn't just skim it!  It seems as though references are extremely important in C++.

    • Alex

      References are super useful, and used all the time to pass class objects to and from functions. We'll cover both of these things in future lessons.

  • Avneet

    I think you forgot to mention an important thing that we can't bind const objects to non-const references.

    C++ 11 introduces r-value references. Can you write a section on it? Thanks.

    • Alex

      Thanks for the tip, it's added now.

      I have r-value references on my to-do list, but it's not high on my priority list right now. They're mostly used for implementing move semantics, which is an interesting but advanced topic.

  • "Note that the second statement may not do what you might expect! Instead of reassigning rev to alias value2, it instead assigns the value from value2 to value1 (which ref is a reference of)."

    "rev" should be "ref"

    Yeps, it's helpful

    Alex, you should try Ginger basic. It is a program that finds out typos and other kind of grammatical errors in your articles.

    Follow This Link

  • Shivam Tripathi

    Alex…in context to one of ur replies to the #comment-7209…i saw that u hv written  "references are implemented using pointers" …it seems u ain’t differentiating b/w "pointers" and "references"…moreover u hv also written that "references" can hv their own address…but i ran a code :-

    and the output is 0x23fe44 for both ‘&ref’ and ‘&value’…doesn’t this contradict ur point…coz pointers hv got their own address…they are lyk real variables…while reference is nothing but just an alias to the actual variable…a "nick-name"…so anyways it will refer to that variable only…thus shares same memory in "stack"…correct me if i am wrong..plzz

    • Alex

      1) The C++ standard does not define how references should be implemented by the compiler, only how they should function.
      2) References are often implemented internally by the compiler using pointers.
      3) In most cases, the compiler can optimize the reference out of existence. In these cases, the reference won't take any memory.
      4) There are a few cases where the compiler can not optimize a reference out of existence. In these cases, the reference will take memory, much as a pointer would.

      Your example above is a case where the compiler will optimize a reference out of existence (it will just replace "ref" with "value").

      • Shivam Tripathi

        okk…got it…but Alex…these different types of references which u mentioned in ur comment…hw are they implemented…i mean what are their use…doesn’t ISO/ANSI declared a single platform of reference….why such partiality…is their any need of such two diff. types of references…where one can take memory & one can’t..

  • very informative thanks

  • Rohan

    Great Website!

    I am pretty confused about the program:
    Furthermore, the reference can not be “redirected” to another variable. Consider the following snippet:

    because i ran a program which was:

    I got the answer 6 6 6
    The value of reference WAS changed.... how?

    • Saksham

      Please read again. He has explicitly mentioned that
      rnRef = nValue2; // assigns value 6 to nValue -- does NOT change the reference!

      In your case too, the VALUE is being changed, not the reference.

      So, if you write a code to check where the 'r' reference is referencing, i'm pretty sure its gonna be 'n'. Or just this code is sufficient :

      int n=5;
      int n1=6;
      int &r=n;

      This will output 6 6 6 4.

      BTW, the articles on this website are the best i have seen so far. Keep up the good work Alex. :)

  • papagym177

    In the code below, nValue is assigned 6 & rnRef is assigner 7. So how do they they get incremented by 1 in the rest of the snippet? This is really confusing.

    nValue = 6; // nValue is now 6
    rnRef = 7; // nValue is now 7

    cout << nValue; // prints 7
    cout << rnRef; // prints 8

    I would think if you reference something it has the same value as what it references.

    • Rohan

      I believe that reference is just the same variable with different name (which is correctly called alias above) the program is read sequentially, thus at first nvalue is assigned value 6, then rnRef is assigned 7 since it is reference the same value is assigned to nValue, thus after execution of Cout it will show 7, after using 'nValue++' the Value assigned to nValue is incremented from 7 to 8, and Since rnRef is same variable with different name, the value of nValue i.e 8 is assigned to rnRef thus we get 8 as output.

  • runner

    the following code does not compile:

    the error is:
    error C2440: 'initializing' : cannot convert from 'const int' to 'int &'

    if the first reference is not const, or both are const, then the code compiles. what is the problem?

    • This doesn't work because you are trying to set a non-const reference to a const value. Making a variable const essentially means the variable is read-only, and can not be written to. When you assign non-const reference rfRef1 to const reference rfValue, you're saying that you want to write to a value that was previously defined as const, which is a violation of rfValue's constness. Const is meant to be a guarantee, not a guideline or something that can be discarded when it's no longer convenient.

      If you want to modify nValue via reference, assign rfRef1 directly to nValue.

  • afds

    So references are basically like typedefs instead that they don't change names of data types but of variables.

    • Alex

      That's an interesting way to look at things. I'm not sure if the analogy holds up in all cases, but speaking generally, yes, since both are ways to provide an alias to another name.

  • Alex, just another happy and impressed reader of your C++ Tutorials. I've been reading the book C++ Primer Plus and it's a good book, but it sometimes overwhelms the student with too much information on what's being taught and not on what needs to be learned.

    Your Tutorial is in my opinion far superior to C++ PP. It has really helped me get a better grasp of this language.

    Thank you for bringing the human element to this tutorial and making it easier to understand.

    Note: You should consider making this Tutorial into a book. It's better than what I've seen being offered out in the world.

    Take care and best of luck in your endeavors.


  • el-mudo

    Hey Alex, I would like to thank you for the GREAT tutorial. It's been very useful for me so far in migrating from C and the simple (very human) language makes it easy to understand even for people with no coding experience

    And good point in the comment up here, i'm pleased to see i'm learning from someone who realy knows what he's talking about xD

    Now, when somebody asks me where to learn cplusplus, it's your site I'll recomend (unfortunately most pleople I know wont be very pleased to have to translate it so then can understand)

    keep the good work!

    (eh, sorry for the bad english)

  • Zafer

    I have a question about the statement: "You can assign const references to literal values, though there is typically not much need to do so: const int &rnRef = 6;"

    In another tutorial, I read that a reference variable needs an accessable address. When we declare a reference variable we can only assign something that has a valid address. In other words, the thing we are assigning should be an l-value. However, constant literals do not have predefined memory address therefore cannot be assigned to a reference variable. Please correct me if I'm wrong.

    • This is a very interesting point, and one for which I can not give you a definitive answer. References are typically implemented using pointers, and pointers must point to an address, which implies the other author is correct in that regard. On the other hand, you can experimentally determine that the above code does indeed compile and perform as expected! As you note, there is a seeming inconsistency between these two things.

      My guess is that the compiler promotes the literal 6 to a constant int, and then assigns the reference to that. To see if I could find any evidence of this behavior, I did a simple test:

      On my machine, this prints 0012FF7C

      On my machine, this prints 0012FF78

      With integers being 4 bytes, note that the second example appears to be doing an extra allocation. This certainly lends support to the theory of the literal being promoted to a constant integer.

      • Zafer

        Yes this theory is meaningful. I don't see however how the second allocation is doing an extra allocation.

        • When you allocate local variables, they are put on the stack. Because of the way stacks work, variables allocated sequentially should be laid out sequentially in memory. For example:

          produces the result:

          As you can see, the first thing allocated was put in 0012FF7C, the second in 0012FF78, and the third in 0012FF74.

          In the first example above, we allocate one variable (nRef), so it gets allocated to 0012FF7C as we would expect.

          The second example is more interesting. In the second example above, we allocate one reference (rnRef)... When we take the address of a reference, it returns the address of whatever it's referencing (not it's actual address). &rnRef returns 0012FF78, which is the second spot available for allocation. If the thing rnRef is pointing to is in the second spot available for allocation, then what's in the first spot?

          The answer is the reference itself!

          If this is true, then the value at address 0012FF7C (which is where the reference actually lives) should be the address 0012FF78 (which is what the reference is pointing at). If we look at the value in memory address 0012FF7C (using a debugger), we see the decimal value 1245048, which is 0012FF78 in hex.

          So it appears the theory is true. The reference itself is being allocated at memory 0012FF7C. It contains the value 0012FF78, which is what the reference is looking at. Memory 0012FF78 has the value 6. The literal value 6 was given it's own memory address so the reference could point to it.

  • Abhishek

    Hey Alex!

    Is it possible to change the value of a constant reference by changing the value of the original variable?
    Like this:

    int nValue = 5;
    const int &rnRef = nValue;
    //what will be the value of rnRef now?

    (Please ignore this question if it dosen't make any sense.......but i hope it does!!)

    • Why not just put this program into your compiler and see what happens? :)

      The answer is yes, you can do this. The fact that we changed the value of nValue does not affect the fact that rnRef is still a const reference to nValue.

      • Abhishek

        "Compilers may go wrong----Alex wont" :-)

        I was just feeling lazy to do that..... :-)
        I'll take care to do that myself next time....

      • papagym177

        This is a pretty dumb question, I wonder why no one has asked it before.

        Is there a program that will take an enter snippets and output it to see what they will do?

        I would think you have to put a snippet into a program format to make them work on most compilers

    • In C++ reference means constant reference.
      To the best of my knowledge there is no difference between reference and constant reference.

      • There is a difference between a reference and a const reference. A reference will let you change the value the reference points to, whereas a const reference will not. However, all references are "const" in the sense that you can not change what the reference points to.

Leave a Comment

Put all code inside code tags: [code]your code here[/code]