Pointers Aren't Just for Array Elements
So far, we've used pointers as a way to refer to array elements.
But array elements aren't the only things in memory. We already know that our regular variables have addresses on the stack, so it shouldn't be a surprise that C++ provides us with a way to find out where they are.
C and C++ actually provide a way to find the memory address of any variable, via the address-of operator, &
. In many ways &
is the opposite of *
.
- The
*
operator takes a pointer (i.e., the address of a thing) and gives you the thing it points to. - The
&
operator takes a thing and gives you a pointer to it (i.e., the thing's address).
So if I wrote
*&x
they'd cancel out and it'd be the same as writingx
?Yes.
But please don't do that.
Yeah, don't.
In fact, in general, you'll almost never use the address-of operator (i.e.,
&var
) in modern C++ code or in code you write for CS 70.And modern C++ code uses
std::address_of
instead.Okay, whatever.
Address-Of Example
void printElephant(const Elephant* ePtr) {
cout << "Elephant named " << ePtr->name_ << endl;
}
int main() {
Elephant charlie{"Charlemagne", 19};
printElephant(&charlie);
}
Notice how we wrote &charlie
to get a pointer to an Elephant
(i.e., an Elephant*
) to pass to printElephant
.
Wait, this is kinda clunky. Why not just use references?
Exactly! Sure, we can do it this way, but why would we?
MORE ways to do things!!!
Mostly it's just C++'s C heritage. C doesn't have references so it has to use address-of to get pointers to pass into functions. But C++ has better options.
In C++ code, it makes more sense to use reference types and not use address-of to pass a pointer.
void printElephant(const Elephant& e) {
cout << "Elephant named " << e.name_ << endl
}
int main() {
Elephant charlie{"Charlemagne", 19};
printElephant(charlie);
}
But pointers can do what references do?
And MORE!!
Yes.
So why have references? They're more limited and we don't actually need them.
That's what the C programmers argue.
In 1979, I created the first incarnation of C++ (called “C with Classes“), and it didn't have references. It wasn't until 1985 that I added references (and called the language C++).
References make some use cases clearer, and the code easier to read.
Two Different Meanings of &
I'm getting a bit muddled. Does
&
for references have anything to do with&
for address-of?No. Unlike
*
where the*
represents different aspects of “pointerness”, for&
the two uses only have a very loose connection to each other.We could say that using reference types (
&
) helps us avoid using the address-of operator (&
) on variables, and that's the connection.Yeah, uh, thanks.
In sum,
In a Type Context | In a Value Context | |
---|---|---|
& |
reference to (used a lot) |
address-of operator (rarely used in C++) |
* |
pointer to | indirection operator |
Pointers vs. References Summary
References are for a very specific use case. One where we'll never change what's being referred to.
- Pointers are more general.
- Pointers have their own storage in our memory model.
- A pointer is a memory address—to get what is actually at that address you need to follow the pointer using the indirection operator (
*
). - Pointers support math, like being added to (but only do so if the pointer is pointing into an array!).
(When logged in, completion status appears here.)