Join Bill Weinman for an in-depth discussion in this video References, part of C++ Essential Training.
- [Instructor] C++ references are very much like pointers but with different rules and semantics. Here I have a working copy of working.cpp from chapter three of the exercise files. Let's take a look at a quick example. I'll start by declaring a variable int i = 5. And I'm going to declare a reference to that variable. Going to say int ir = i. So that's the integer reference that is referring to the variable i with the value of five, and now I'm going to say ir = 10 and I'm going to go ahead and print it.
What I'm going to print is i not ir. And now you'll notice when we build and run here that i is 10 and that's because I assigned 10 to the reference which is referring to i. So a reference works very much like a pointer but with some significant differences. The syntax of assigning a reference is different and does not involve using the address of operator. The syntax of getting the value referred to by a reference does not involve the value of or de-reference operator.
You cannot refer to the reference itself. That is you cannot take a reference of a reference. You cannot have a pointer to a reference and you cannot have an array of references. The reference cannot be null, cannot be un-initialized, and cannot be changed to refer to another variable. So if we look at our example here, you see that I'm assigning this variable i to this reference and so now this reference, it's like an alias to the variable itself.
I can use it without any de-reference operator and when I change its value, its value is the same as what's referred to. So i and ir, from the perspective of how they're used, are exactly the same and refer to exactly the same memory space and exactly the same variable. Now let's look at a common usage because this kind of usage here is actually good for explaining but, it doesn't really have much use in the real world.
But let's say that I have a function, and this function returns a reference to an integer and it takes as its argument a reference. And it operates on that so it's, return ++i so it's going to take that integer, that should be i there, there we go, and it's going to increment that value and return that value. But everything involved here is references right? And so now I'm going to come down here after my printf and I'm going to say printf, let's put it in quotes f() is %d f(i) like that.
And then I'm going to printf i again. We can do it this way. Now when I run this you'll notice a couple of things are happening here. f returns 11 because it takes a reference to i and it increments it and it returns a reference to that. So it's returning i and i is 10 here and then it increments it to 11 and so f is returning 11. And now i is also 11 when we print i after it's passed to the function.
So while we can see that this is useful where you don't want to have to copy some object of unknown size for every function call, and that's frankly what it's used for a lot, the downside is that unless you look at the function's signature, there's no way by just looking at this here, there's no way of knowing that it has side effects. That i is actually affected and that's a serious downside. In fact what I can do here is I can say = 42 and now when we run it, i is actually changed to 42 because you see this is returning a reference to something that is referenced when it's passed in.
So these side effects are not obvious. Now I can mitigate a lot of these side effects by doing this. Now you'll notice a few things are happening here. A lot of what I'm trying to do here is no longer allowed. This assigning the 42, that's no longer allowed, because what f returns now is a const reference. So it's const-qualified and it can't be changed and in fact even inside of the function I now need to say int local i = i and now passing the reference is almost useless.
And now when I run this you'll see that my side effect is no longer there. So my recommendation is to use pointers when you want to be able to have side effects because then it's obvious as you're using it, that there are pointers involved and that side effects are possible. Use references only where you can use const as I have here. But you need to be aware that not everyone agrees with my opinion on this. There's a lot of code out there that use non const references including quite a bit of the standard template library.
So you just need to be conscious that this effect is possible and look at your function signatures, especially on library code. References are very powerful and they're very common in C++ and we'll be using references quite a bit and you will gain much more experience with them, over the course of taking this Course.
- Setting up Xcode and Visual Studio
- Statements and expressions
- Primitive arrays and strings
- Data types
- Classes and objects
- Standard Library and Standard Template Library