Pointers and memory

Intermediate

Introduction

Everything in a program lives at an address in memory. Pointers let you work with those addresses directly. Modern C++ needs them much less than C does, but they remain essential for understanding how the language works and for reading real code.

How it works

&x gives the address of x. A pointer, written int* p, stores an address. *p follows the pointer to the value it points at. A pointer that points at nothing should hold nullptr, and following it is a serious error.

Pointers and references. Both refer to something else, but a reference must be connected when it is made and cannot be moved to another variable. A pointer can change where it points, and it can be null. Use a reference when you can, and a pointer when you need those extra abilities.

The heap. new creates something that lasts until you delete it, whatever function you are in:

#include <iostream>
using namespace std;

int main() {
    int n = 3;
    int* scores = new int[n];
    for (int i = 0; i < n; i++) {
        scores[i] = (i + 1) * 10;
    }
    cout << scores[0] + scores[1] + scores[2] << endl;
    delete[] scores;
    scores = nullptr;
    return 0;
}
Open in compiler

The array form needs the matching delete[]. Forgetting to release memory causes a memory leak, and using it afterwards is a serious bug.

Why this is less common now. A vector or string calls new and delete for you, at the right times, even if an error occurs. So modern C++ code rarely needs to call them directly. You will still meet them in older code, and when you build data structures such as linked lists.

Syntax

int* p = &x;
*p = 5;
int* one = new int(7);
delete one;
int* many = new int[n];
delete[] many;

Example

#include <iostream>
using namespace std;

int main() {
    int x = 10;
    int* p = &x;
    cout << *p << endl;
    *p = 20;
    cout << x << endl;
    int* nothing = nullptr;
    cout << (nothing == nullptr) << endl;
    return 0;
}
Open in compiler

Line by line

  1. p holds the address of x.
  2. *p reads x through the pointer, giving 10.
  3. *p = 20 changes x without naming it.
  4. nothing is set to nullptr.
  5. Comparing it with nullptr prints 1, for true.

Expected result

10
20
1

In the real world

Pointers are how a program reaches hardware and shares large objects. Memory errors are so costly that large organisations now recommend languages or tools that prevent them, and modern C++ style exists largely to avoid raw new and delete.

Common mistakes

  • Following a null or uninitialised pointer.
  • Using delete on memory from new[]. Use delete[].
  • Using memory after deleting it.
  • Forgetting to delete, which causes a leak.

Best practices

  • Set a pointer to nullptr if it has nothing to point at.
  • Prefer references to pointers for function parameters.
  • Prefer vector and string to new[].

Summary

Pointers store addresses, * follows them, and nullptr means nothing. new and delete manage heap memory by hand, and must be matched exactly. Containers usually do this job for you.

Quick check

1. int x = 1; int* p = &x; *p = 4; What is x?
2. Which releases memory from new int[5]?
3. What can a pointer do that a reference cannot?
4. Why is vector usually better than new[]?

Key takeaways

  • &x gives an address, and *p follows one.
  • Every new needs one delete, and every new[] needs one delete[].
  • Prefer containers to raw new and delete.

Practice problems for this lesson

My notes

Write down what you want to remember from this lesson. Notes are saved on this device as you type, and appear on your dashboard.