4.1. Introduction To Pointers

Time: 00:04:33 | Download: Large, Large (CC) Small | Streaming, Streaming (CC) | Slides (PDF)

 

Terminology

This chapter relies extensively on terminology introduced in earlier chapters. Please review these terms as needed:

An xkcd cartoon about pointers.
Pointers cartoon. https://xkcd.com/138/

Pointers are surprisingly powerful and, therefore, immensely useful. Most aspects of programming use pointers in one way or another. Even languages like Java that have ostensibly eliminated pointers rely heavily on them. The interdependence of pointers with other programming features makes choosing the best presentation sequence difficult. Most of the programming features presented in subsequent chapters rely, at least in part, on pointers, suggesting their early presentation. Yet, without the context of those features, pointers have little utility, detaching them from practical programming and making authentic examples difficult to find. So, the text introduces pointers first, with minimal forward references. It relies on your previous experience with Java or Python to provide the necessary background, revisiting the advanced programming features in upcoming chapters where it adds detail, context, and examples.

Shortcuts

Our first and most significant challenge is understanding pointers at a fundamental level. So, we begin with an analogy based on a more familiar feature: shortcuts (Windows) or symbolic links (Unix/Linux/macOS). A file is a collection of related information with a human-readable name. Operating systems maintain the file's contents on secondary storage (e.g., disk or flash drives) and its name in a directory or folder. They display the file's information with different system programs (e.g., Windows Explorer, dir, tree, ls, etc.). An absolute pathname uniquely denotes the file's location within the file system.

Once we create a file, shortcuts allow us to have additional names for the original file. Three variations of the additional names provide convenience and flexibility:

A Rectangle representing an executable file or program. The file has an address or location on a disk drive that we can express as an absolute pathname. We create a shortcut or symbolic link with two files, represented in the figure as two rectangles. The first file is a program that has a physical drive address. The second file is the shortcut or symbolic link and contains the absolute pathname of the first file.
(a)(b)
Files and Shortcuts. The relationship between files and shortcuts or symbolic links and how operating systems use them mirrors data and pointers. Like a shortcut, the contents of a pointer is an address. But where a shortcut has a file system address (i.e., a pathname to a file), a pointer has some data's address in main memory.
  1. A file and its location specified as an absolute pathname.
  2. A shortcut creates a new name for an existing file. The shortcut file's contents are a pathname to the "real" or "normal" file. The example uses an absolute pathname, but relative paths are also allowed.

In this example, the file is an executable program. It's a common practice to put shortcuts for frequently used programs on the desktop. If I launch the Spotify program by double-clicking the shortcut in the Desktop directory. The computer first opens and reads the shortcut file and then opens and runs the Spotify executable file named in the shortcut file. Shortcuts require the operating system to open and read an additional file, slowing the program's startup. But shortcuts are typically much smaller than a program file. So, on balance, the slight startup overhead allows me to have one program file and as many shortcuts as I want, wherever convenient.

C++ Pointers: C++ vs. Java

As we study pointers, we must include two concepts not formally introduced until later chapters: arrays and classes. We'll use these topics without much detail, revisiting arrays in Chapter 7 and classes in Chapter 9. Until then, we'll rely on your experience from last semester. At the conceptual level, C++ and Java are very similar. For those of you who are beginning C++ without the benefit of CS 1400 or previous Java experience, the review section in Chapter 1 will fill in some of the needed detail and the remaining forward references are brief and undetailed.

We begin our discussion of pointers by exploring a simple statement in Java. Suppose that a Java program declares a class named Person and that it has two instance fields named name and id, respectively. In that case, we can illustrate the statement and its impact on memory with the following illustration. Java textbook authors often claim that Java does not have pointers, which is technically correct - Java has references; however, the distinction between a pointer and a reference is very subtle. The key to understanding the following figure is that variable p points to the Person object, wherever it is in memory. The same picture can also apply to a similar operation in C++.

Person p = new Person(); An abstract representation of what occurs in memory when a Java program creates an object. A large box represents a Person object that contains two fields. The new operator creates the object. A small box labeled p represents a variable that holds the object's address. An arrow from p to the object denotes the address, so we say p points to the object.
(a)(b)
Instantiating an object in a Java program. Person names a class with two instance fields: name and id.
  1. On the left side of the assignment operator, the code Person p, does not create an instance of class Person - it defines a variable that can hold the address of a Person object; the right side of the assignment operator, new Person(), instantiates an object and returns the address of that object.
  2. The illustration suggests how we might visualize the effect of the code in (a). The small box labeled p represents the variable p while the large box represents the Person object; the two smaller boxes inside the large box represent the instance fields contained inside the Person object.

We can create objects in a C++ program the same way we do in a Java program. So, the (b) parts of Figures 2 and 3 are identical, and the (a) parts are very similar. The challenge is that C++ can create objects in multiple ways, whereas Java, ignoring a couple of exceptional cases, can create them in only one way. C++'s increased flexibility requires additional syntax and a deeper understanding of memory management to appreciate which method is best in a given situation. Figure 3 illustrates the syntactic options and the associated abstract representations associated with C++.

Person* p = new Person; This picture is the same as used to illustrate object creation in a Java program. The C++ syntax differs slightly from the Java syntax, but the abstract representations are the same: A large box represents a Person object containing two fields. The program creates the object with the new operator. A small box labeled p represents a variable that holds the object's address, and an arrow pointing from p to the object denotes the address - again, p points to the object.
(a)(b)
Person p; This C++ code creates an object named p but does not create a pointer. The illustration consists of a large box representing the object, with two smaller boxes inside representing the two fields, name and id.
(c)(d)
Two ways to instantiate an object in a C++ program. Person again names a class with two instance fields: name and id.
  1. The code Person* p defines a pointer variable; new Person; creates a Person object and returns its address, which the assignment operator stores in the pointer variable. (Notice that parentheses before the terminating semicolon are optional.)
  2. The illustration is the same as Figure 3(b), which suggests that at a fundamental level, Java and C++ behave in the same way - both languages use pointers to manipulate objects
  3. The code Person p; creates a new Person object, but the variable p directly names the object. Late in the chapter, we'll learn that the object's name, p, represents its address.
  4. Unlike Java, C++ can also create an object as an automatic variable on the stack

All of the above suggests that while pointers and their associated syntax can be conceptually challenging to understand, learning how to use them to solve problems is well worth the time and effort it may take. Pointers are a kind of variable that allows programmers to work with memory addresses, so we begin by exploring the relationship between variables and addresses.