Concepts / Pointers and References to Objects

Pointers and References to Objects

The key habit is that a concrete object is handled the way you handle an int. You do not think about where it is stored. You name it and use it.

  • Programming

Two Questions About Every Object

Whenever a program creates an object, two questions matter in practice. The first is where the object lives in memory, because that determines how long it stays available and how it is created. The second is how the rest of the program reaches it once it exists. The answers differ depending on whether the object belongs to a concrete class or to a class that takes part in a class hierarchy.

This article follows that difference step by step. By the end, you should be able to predict how a given object will be created and reached before you read the code that does it. We will start with the simpler case, concrete classes, and then move to hierarchy objects, which need a different kind of access.

Concrete Classes Behave Like Built-In Types

Concrete classes, especially those with small representations, are much like built-in types. You define an object of such a class as a local variable, you access it directly through its name, and you can copy it around the program. Nothing about the object requires you to go through an intermediate reference to reach it. The object is simply there under the name you gave it.

Key point

The key habit is that a concrete object is handled the way you handle an int. You do not think about where it is stored. You name it and use it.

This is the reason concrete classes are described as built-in-like. A reader who already understands how a plain integer variable is named, assigned, and passed around already has most of the mental model needed for a small concrete class. The object's own name is enough to reach it, and there is no separate step of following a handle to find it.

Naming, Copying, and Local Definitions

Consider three things you can do with a concrete object. You can define it as a local variable inside a function, so it exists while that function runs. You can refer to it by its name every time you need it. And you can copy it, producing a value that you can then use independently. In each case, the name is the route to the object. You never need to ask where the object sits or follow a separate pointer to reach it.

Worked example

Using a small concrete object by name

A program needs a small object of a concrete class for a short calculation inside one function. How is the object defined, reached, and copied?

  1. 1
    Define the object as a local variable

    The object is declared inside the function, so it is simply there under its chosen name for the duration of the function.

  2. 2
    Access it through its name

    Each time the calculation needs the object, the code uses the name directly. No intermediate reference is required.

  3. 3
    Copy it when a second value is needed

    The object can be copied, so the program can work with a copy of the value while keeping the original under its name.

Result

The concrete object is used exactly like a built-in value: defined locally, named directly, and copied when needed.

Hierarchy Objects Live on the Free Store

Classes in class hierarchies follow a different pattern. Their objects are typically allocated on the free store using new, and they are typically accessed through pointers or references rather than by their names alone. The object itself is created by new. The name you hold is not the object. It is a handle that leads to the object.

local concreteobjectused directly by namelocal pointer pholds a handlehierarchy objectcreated by newleads to
Where does each object physically live, and what does a local pointer variable hold compared with the object it leads to on the free store?

The diagram shows the split. On one side is a local variable, which here is a pointer. On the other side is the object it refers to, which lives on the free store. The concrete object on the stack side is reached by its own name, which is the contrast this article is about. The hierarchy object is reached only by following the pointer.

What do you think happens?

If you copy a pointer to a hierarchy object into a second pointer variable, how many objects exist afterward?

  • Two objects, one for each pointer

  • One object, which both pointers lead to

Reveal answer
Answer:

One object, which both pointers lead to.

The pointer is a handle that leads to the object. Copying the handle gives you a second route to the same object. It does not create a new object, which is why the copied pointer and the original pointer both reach the same place.

Why a Name Is Only a Handle

Notice what this changes. The object is not reached by the name of a local variable sitting next to it. It is reached by following the pointer. A reference works in the same spirit. It gives you another way to refer to the object without making a copy of it. In both cases, the program keeps working with the object that was created, rather than with a duplicate of it.

This is why hierarchy objects are accessed through pointers or references rather than by name alone. Reaching the object through a handle keeps the object itself in one place, on the free store, and lets the rest of the program refer to it from wherever the handle is held. The name you hold is only the route; the object is what was created with new.

Tracing a Shape-Reading Function

The source introduces the pattern with a function that reads data describing shapes from an input stream and constructs the appropriate Shape objects. The important point is that the program does not know in advance which concrete kind of shape each piece of data describes. It decides while reading, and then it creates the matching object.

read shape datafrom the input streamdecide the kindwhich concrete shapenew creates objecton the free storestore the pointerkeep a handlecaller reachesobjectsthrough the pointersnextcreatekeepreturn access
In what order does the function read the input, call new for each shape, store each pointer, and how does the caller later reach those objects?

Read the diagram in order. The function reads one piece of shape data, decides which concrete kind it describes, and calls new to create an object of that kind. Because the object belongs to a class hierarchy, it is allocated on the free store. The function then stores a pointer to that object. The same steps repeat for each shape in the input, so the function may end up holding many pointers, each leading to its own object.

Worked example

Tracing one shape through the function

The input contains a description of one shape. Follow it from reading to later access.

  1. 1
    Read the description

    The function reads the data for one shape from the input stream.

  2. 2
    Choose the concrete kind

    The data tells the function which concrete kind of shape it describes. The program learns this only at this moment, while reading.

  3. 3
    Create the object with new

    new allocates an object of that kind on the free store.

  4. 4
    Keep a pointer

    The function stores a pointer to the new object, so the object can be reached after the function has finished reading.

  5. 5
    Reach it later

    Later code follows the stored pointer to get at the object, rather than looking for it under a local name.

Result

The object exists on the free store, and the program reaches it afterward through the stored pointer.

Mistakes Beginners Make with Handles and Objects

  • Common mistake

    Treating the pointer variable as if it were the object

    Why it fails

    The source describes the name held for a hierarchy object as a handle that leads to the object, not the object itself. The object was created by new and lives on the free store.

    Do this instead

    Think of the pointer as a route. To use the object, follow the pointer to reach it.

  • Common mistake

    Expecting a hierarchy object to be reached by a local name the way a concrete object is

    Why it fails

    A concrete object is accessed directly through its name. A hierarchy object is typically accessed through pointers or references rather than by its name alone.

    Do this instead

    When an object belongs to a class hierarchy, look for the pointer or reference that leads to it before trying to use it.

  • Common mistake

    Assuming that copying a pointer copies the object

    Why it fails

    Copying a pointer gives a second route to the same object. The object is not duplicated, so both routes reach one object.

    Do this instead

    Copy a concrete object when you want a separate value. Copy a pointer only when you want another way to reach the same object.

Concrete Objects Compared with Hierarchy Objects

AspectConcrete class objectHierarchy class object
Typical definitionLocal variableCreated with new on the free store
How it is reachedDirectly by its nameTypically through a pointer or reference
CopyingCan be copied around the program like a built-in valueAccess is through a handle; copying the handle does not copy the object
Where it is handled likeA built-in type such as intAn object reached through a handle

The first column shows how a concrete class is typically used. The second shows how a class in a hierarchy is typically used.

Read down each column to see the full pattern. The concrete column describes an object you can simply use. The hierarchy column describes an object you reach through a handle that was stored when the object was created.

Check Your Model

MEDIUM

A function reads three shape descriptions from an input stream. For each one it creates a hierarchy object with new and keeps a pointer to it. Afterward, the caller needs to use all three shapes. Explain, in your own words, where each object lives, how the caller reaches it, and why a plain local name would not be enough to do this.

Hints
  • Ask where new places an object for a class in a hierarchy.
  • Think about what the function keeps after it has finished creating each object.
  • Compare how a concrete object is reached with how a hierarchy object is reached.

Key Takeaways

  • Concrete classes, especially those with small representations, are used much like built-in types: defined as local variables, accessed by name, and copied around.
  • Objects in class hierarchies are typically allocated on the free store using new.
  • Hierarchy objects are typically accessed through pointers or references rather than by their names alone; the name held is a handle that leads to the object.
  • A reference gives another way to refer to an object without making a copy of it, and copying a pointer gives a second route to the same object.
  • A function that reads shape data decides the concrete kind while reading, creates each object with new, and stores a pointer so the objects can be reached later.

Related concepts

More concepts starting with P