CIS 3142 Advice — Chapter 7

CISC 3142
Programming Paradigms in C++
Part II: Basic Facilities
Chapter 7 — Pointers, Arrays, and References

Reading from the Text

Chapter 7 — Pointers, Arrays, References

Overview

This chapter presents pointers, arrays, and references. They appear in the same chapter because they are related: Here is a write-up on pointers, arrays, references, and several related topics

Topics

Pointers

void *
nullptr

Arrays

Array Initializers
String Literals

Pointers into Arrays

In a nutshell, once declared, an array (or at least its variable name) is basically a pointer to the first element.
Navigating Arrays
Passing Arrays
C-Style Strings (char *)
C — which did not have classes, and the ability to have the resource-handle memory management available in C++ — represented strings as arrays of characters. They are often referred to as char * because of the close relationship between arrays and pointers. Here is a write-up on C-Style Strings. They're ubiquitousness in C has been heavily reduced in C++ because of the higher-level string class that handles its own memory management and provides a much more intuitive interface via operator overloading. However, there are still several reasons for being at least acquainted with C-Style strings and their processing idioms:

Pointers and Ownership

The crucial issue is … once an object has been (dynamically) allocated on the free store (heap), who is responsible for that memory, i.e., who owns it?

References

Unlike pointers, references do not maintain their own identity, nor do they require special machinery (such as * or -> to access what they refer to (their alias).

Advice

  • [1] Keep use of pointers simple and straightforward; §7.4.1.
    • pointer use should be restricted for the most part to holding addresses (handles) of dynamically allocated memory
    • no need to use them to simulate call-by-reference (because we now have actual call-by-reference in C++)
    • rare need to use them for systems-programming
  • [2] Avoid nontrivial pointer arithmetic; §7.4.
    • most processing involving such arithmetic can be done via subscripting
  • [3] Take care not to write beyond the bounds of an array; §7.4.1.
    • contrast with Java bounds-checking
  • [4] Avoid multidimensional arrays; define suitable containers instead; §7.4.2.
    • if we reduce use of arrays (advice 7.6), this becomes a total non-issue
    • even if we stick with arrays, most multi-dimensional arrays (like most nested loops) can be decomposed into layers of responsibility
      • A two-dimensional array consisting of the 5 exams for 20 students in a class is better represented as an array of 20 student objects, each containing an array of 5 exams
  • [5] Use nullptr rather than 0 or NULL; §7.2.2.
    • nullptr is an entity known to the compiler, which can then take language semantics into consideration while 0 and NULL don't
  • [6] Use containers (e.g., vector, array, and valarray) rather than built-in (C-style) arrays; §7.4.1.
    • They take care of their own memory management, provide a richer set of operations than arrays, and often maintain the integrity of the structure through invariants
  • [7] Use string rather than zero-terminated arrays of char; §7.4.
    • string is the container equivalent of zero-terminated arrays (char *)
  • [8] Use raw strings for string literals with complicated uses of backslash; §7.3.2.1.
  • [9] Prefer const reference arguments to plain reference arguments; §7.7.3.
    • If something can be declared const as a parameter, it means it value is not being changed in the function. Enforce that with const.
  • [10] Use rvalue references (only) for forwarding and move semantics; §7.7.2.
  • [11] Keep pointers that represent ownership inside handle classes; §7.6.
    • The constructor and destructor of the handle class then becomes responsible for the pointers lifetime and management
  • [12] Avoid void * except in low-level code; §7.2.1.
    • void * is a 'typeless' pointer that was used in C to bypass the restriction on pointers in C.
      • This was occasionally necessary in system-programming
    • It also provided an 'escape hatch' for memory allocation functions
      • C++ eliminating this need with the new operator (which is known to the compiler)
    • It has little to no use in C++ — except for the referred-to low-level programming.
  • [13] Use const pointers and const references to express immutability in interfaces; §7.5.
    • Including const in a parameter type declaration or return value conveys important and useful information about the function
  • [14] Prefer references to pointers as arguments, except where 'no object' is a reasonable option; §7.7.4.
    • References are simpler to work with, and involve less machinery on the part of the programmer