C++ Pointers

An introduction to pointers - a more powerful type of reference, that carries some additional capabilities.
This lesson is part of the course:

Intro to C++ Programming

Become a software engineer with C++. Starting from the basics, we guide you step by step along the way

3D art showing a female blacksmith character
Ryan McCombe
Ryan McCombe
Posted

Previously, we introduced reference variables. These were a way to, indirectly, have two variables pointing to the same location in memory.

Working with memory addresses is often considered quite dangerous - it can introduce some nasty bugs if not managed correctly.

Because of this, references had two restrictions, designed to ward off the most common cause of those bugs:

  1. References must be initialised with a value
  2. References cannot be reassigned

Unfortunately, sometimes our software does need to do these things. For this reason, we have pointers. We can think of pointers as references, but without the safety barriers.

The Address Of Operator - &

We can get the address of where a variable is stored in memory by using the & operator. This is referred to as the address-of operator.

int x { 1 };

// Log out the location of x in memory
cout << &x;

The above program will output a memory address, which may look something like 0x7ffe88a53e88.

Pointers are generally considered the most confusing topic learners encounter in C++ journey, and the use of & here is one of the reasons why.

Didn't we already see & being used with references?

Confusingly, the & token has a different meaning depending on where it appears in our code.

When we use the & syntax with a data type, we are saying we want to work with a reference to that data type, as in the below example:

int x { 5 };

// Create a reference to x
int& ReferenceToX { x };

When we use & with a value that has an identifiable memory location, such as the the name of a variable, & is an operator. It is going to operate on that variable - specifically, it will get its memory address

int x { 5 };

// Find out where x is stored in memory
&x;

Test your Knowledge

How can we find the memory address used by the isDead variable?

bool isDead { false };

C++ Pointer Types

What gets returned from the & operator is referred to as a pointer. It points to a location in memory. A pointer is a value like any other - it can be stored in variables, stored as members of a class, handed off to functions and more.

Any code that has access to the pointer can visit that memory location, read what's there, and make changes to it.

Pointers are also strongly typed - we need to declare what type of data a pointer points to.

We identify it as a pointer by adding an asterisk after the type - *

For example, if we wanted a variable called MyPointer to store a pointer to an int, we could declare it like this:

int* MyPointer;

Similarly, if we use the address of operator, & on a variable containing an int, we will get an int*.

That is, we will get a pointer to an int:

int x { 1 };
int* MyPointer { &x };

Pointers can point to any data type:

bool b { true };
bool* PointerToB { &b };

Character Player;
Character* PointerToPlayer { &Player };

Test your Knowledge

How can we create a variable called FloatPointer to store a pointer to a float?

Using Pointers in C++

With references, we could just work with the reference as if it were the base data type. We could use a reference to an int (an int&) as if it were an int.

We can't do that with pointers. To access the value that a pointer points to, we need to dereference it. That can be done by prepending the * operator to a pointer.

int x { 50 };
int* PointerToX { &x };

cout << PointerToX << endl;
cout << *PointerToX << endl;

This program will output something like 0x7ffc51be656c, followed by 50.

Again, the use of * here is likely to cause confusion. Similar to &, the * syntax has a different meaning, depending upon where it appears in our code.

When attached to a data type, as in int*, the * indicates we want to work with a pointer to that data type.

However, when we use * with something containing a pointer, as in *MyPointer, it acts as an operator.

That is, it's an instruction to do something with that pointer. Specifically, it's a request to go to that memory location, and get the value that is stored there.

C++ Pointers vs References

To put all these concepts together, lets look at how we can get our Increment function that we originally implemented with references to use pointers instead. Here's the version using a reference:

void Increment(int& Number) {
  Number++;
}

int x { 1 };
Increment(x);

And here it is using a pointer:

1void Increment(int* Number) {
2  (*Number)++;
3}
4
5int x { 1 };
6Increment(&x);
7

The notable changes here are:

On line 1: Our function no longer accepts an int& (a reference to an integer). Instead, it now expects an int* (a pointer to an integer)

On line 2: Our function body can no longer treat Number as an integer. It is now a pointer, so we now need to dereference our pointer before accessing or modifying its value

Note the introduction of the ( and ) here is to ensure the dereferencing operator * happens before the increment operator ++.

We explain this quirk, and operator precedence in general in the next lesson.

On line 6: We can no longer just pass an int into our function and have the compiler implicitly convert it to the correct type for us automatically.

When using a pointer, we need to be more explicit. Therefore, we use the address of operator & to ensure our function receives the pointer it expects.

Test your Knowledge

What should we put in the body of this function to double the value pointed at by the Number pointer?

void Double(int* Number) {
  // ??
}

Now that we've introduced pointers, it would be easy to dismiss references as being unnecessary. Pointers can fulfill the same need and more, given they are less restrictive.

However, references do have their benefits. The above code samples hopefully demonstrate that references are a bit easier to work with. Our reference example has less and simpler code than our pointer example.

Additionally, the restrictions put on references are with good reason. In more complicated examples, the additional work of managing pointers can get a lot more complex.

So, it's a general good practice to prefer references where possible. We should only use pointers when restrictions around references make them unusable for the specific problem at hand.

In the next lesson, we will explore pointers more, and see how we can use them more effectively.

Was this lesson useful?

Ryan McCombe
Ryan McCombe
Posted
This lesson is part of the course:

Intro to C++ Programming

Become a software engineer with C++. Starting from the basics, we guide you step by step along the way

References and Pointers
3D art showing a progammer setting up a development environment
This lesson is part of the course:

Intro to C++ Programming

Become a software engineer with C++. Starting from the basics, we guide you step by step along the way

Free, unlimited access!

This course includes:

  • 66 Lessons
  • Over 200 Quiz Questions
  • Capstone Project
  • Regularly Updated
  • Help and FAQ
Next Lesson

C++ Operator Precedence and the Arrow Operator

Learn more about pointers, and how we can use the arrow operator to make our code more readable
3D art showing a female blacksmith character
Contact|Privacy Policy|Terms of Use
Copyright © 2023 - All Rights Reserved