Search

Admin

6.11 — 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 can be dereferenced to retrieve the value at the address they point to.

References are the third basic type of variable that C++ supports.

References

A reference is a type of C++ variable that acts as an alias to another variable. References are 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”.

In most cases, references act identically to the variables they’re referencing. Let’s take a look at references in use:

This code prints:

7
8

In the above example, ref and value are synonymous.

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

References are implicitly const

References are implicitly const. Like normal constant objects, references must be initialized:

References must always be initialized with a valid object. Unlike pointers, which can hold a null value, there is no such thing as a null reference.

Because references are implicitly const, a reference can not be “redirected” to another variable. Consider the following snippet:

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

Const references

Although references are implicitly const, it is possible to declare a const reference:

A const reference treats the value it is referencing as const. Much like a pointer to a const value, a const reference can reference a non-const variable. When accessed through a const reference, the value is considered const even if the original variable is not.

Const references to literal values

You can assign const references to literal values, though there is typically not much need to do so:

References as function parameters

Most often, references are used as function parameters because they allow us to pass a parameter to a function without making a copy of the value itself (we just copy the reference).|

In lesson 6.8 -- Pointers and arrays we talked about how passing a pointer argument to a function allows the function to dereference the pointer to modify the argument’s value directly.

References work similarly in this regard. A function that uses a reference parameter is able to modify the argument passed in:

This program prints:

5
6

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!

This is useful both when the function needs to change the value of an argument passed in, or when making a copy of the argument would be expensive (e.g. for a large struct).

References as function parameters can also be const. This allows us to access the argument without making a copy of it, while guaranteeing that the function will not change the value being referenced.

We’ll talk about reference parameters in more detail in the next chapter (on functions).

References as shortcuts

A secondary 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 const pointer that is implicitly dereferenced when accessed. Thus given the following:

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

Similarly, a const reference acts just like a const pointer to a const value that is implicitly dereferenced.

Because references must be initialized to valid objects and can not be changed once set, references are generally much safer to use than pointers. However, they are also a bit more limited in functionality.

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).

6.12 -- Member selection with pointers and references
Index
6.10 -- Pointers and const

35 comments to 6.11 — Reference variables

  • 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;
    
    nValue=7;
    //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

        Alex,
        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.

        • matt ernshaw

          following on from this - does that mean that ‘int& const myRef’ is essentially the same thing as ‘int& myRef’ ?

        • stupi

          Alex, is this?
          int nValue = 5;
          const int &rnRef = nValue;

          rnRef=7;
          the complier was wrong, that means we can’t change the value of conts reference.

    • amjad

      it will be 7

      because the rnRef is constant alias of nValue
      we can not make indirection by rnRef but we can do by nValue

  • 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:
          0012FF7C
          0012FF78
          0012FF74

          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.

  • 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)

  • Hi alex,
    doing great job .
    i am fresher attending campus placement.
    please mention which topics in C++ needs to be focussed from interview point of view.
    also post some tricky questions associated with c++ and reference variables which wil be useful for us in interview.

    continue job for welfare of programmers!!!!!!!!!!!!!!!!!!

  • 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.

    Dennis

  • afds

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

  • 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.

  • 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
    nValue++;
    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.

  • 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;
      r=n1;
      cout<<r;
      cout<<n1;
      cout<<n;
      n=4;
      cout<<r;

      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. :)

  • very informative thanks

  • 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..

        • Alex

          There aren’t different types of references. There is only one type of reference. In most cases, the compiler can optimize the reference away so it doesn’t use memory, but there are some cases where it can’t.

  • This example is a bit messy:

    1. No type declared for real(nValue) and reference(rnRef) variables
    2. rnRef is not declared as a reference variable and never referencing to nValue. Thus, the 2nd line doesn’t make any sense (I think :-))

    Can we say that a reference variable acts like the shadow of the variable it is referencing to?

    • Alex

      Shadowing has a different meaning in C++ (a local variable with the same name as a global variable shadows (hides) the global variable when the local variable is in scope).

      Alias is probably a better term.

      I’ll update the example when I rewrite the lesson (soon).

  • Alex, you can add a line in the "Const references" section that "a const reference variable(const int &ref) can only read a value and can’t overwrite the value of the variable that it is referencing."
    This makes a lot of things clear.

  • "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

Leave a Comment

  

  

  

three × 2 =

Put C++ code inside [code][/code] tags to use the syntax highlighter