As you know, an iterator is a reference to an element in a data structure (or container). The concept and use of iterators is influenced by more primordial concepts like pointers and arrays. You will usually not need to use pointers or arrays, but the time will inevitably come when you will need to use them to fix bugs or performance bottlenecks.

In this reading, we will explore the ugly truths of what belongs to the realm of "low-level programming".

Pointers

The most difficult concept for beginning computer science students to grasp is Pointers, yet it is the most fundamental building block of computer software. Many programming languages that are considered difficult to use reveal the concept of pointers while the easier programming languages have chosen to conceal this concept from the programmer.

Whether a programming language reveals or conceals the concept of pointers does not affect the reality that pointers are always in action when the source code is executing.

So what is a pointer? A pointer is the location of a variable in your program, it is synonomous with a memory address. You may access a variable through a pointer or you can assign a pointer to the location of a different variable.

You can have multiple pointers refer to the same variable, thus enabling seperate functions to operate on one variable.

References are a closely related concept to pointers, so if you already know how references work then understanding pointers should be easier. Let's start by looking at two snippets of code that have the same effect:

This example uses a reference:

int x = 5; int& r = x; r = 6; cout << x << endl; ++x; cout << r << endl;

This example uses a pointer:

int x = 5; int* p = &x; *p = 6; cout << x << endl; ++x; cout << *p << endl;

Both examples display the integer values 6 and 7. Although it appears that references fulfill the same basic purpose as pointers and are easier to use, they come with a disadvantage: references must be bound to a variable the moment they are created and cannot be unbound.

A pointer, on the other hand, can be rebound to a new variable at any time. The statement int* p = &x means "create integer pointer p and assign it to the address of x". The & operator is known as the address-of operator: when used on a variable, it returns a pointer to that variable. Remember that a pointer is simply a memory address, thus getting the address of a variable is the same as getting a pointer to a variable.

The address-of operator works on any variable, including pointer variables. Taking the address of an int gives you a value of type int* (integer pointer) and taking the address of a int* variable gives you a value of type int** (integer pointer pointer). The process can go on.

To access the variable being referenced by a pointer, we use the * operator (known as the dereference operator). If p is an integer pointer, then the expression *p means "get integer variable pointed to by p".

Arrays

An array is a more primitive form of vector. Like a vector, it can store multiple elements and each element is indexed 0 to N-1 where N is the number of elements. Unlike a vector, an array cannot add new elements; there is no push_back member function on an array. You cannot erase elements from an array either. In fact, arrays do not have any member functions at all.

Arrays are what programmers used before vectors were invented. There is nothing wrong with using them today, using an array when you do not need the extra functionality offered by a vector can give make your program faster; but keep in mind that they are more difficult to use, especially for beginners.

Let's begin again by looking at two examples that have the same effect. One uses a vector and the other uses an array:

int a[3]; a[0] = 500; a[1] = 3; a[2] = 40; vector<int> v(3); v[0] = 500; v[1] = 3; v[2] = 40;

Variable a is an array of three integers. It takes up the same amount of memory as if we declared three seperate integer variables. Pretty much the only operator you can use on arrays after they are declared is the subscript operator. Unfortunately, you cannot assign an array to another array, even if they are the same size: but you could iterate over the elements in one array, copying each element to an element in another array.

int a[3] = {1,2,3} // Ok: Create array of integers and use initializer list to initialize the elements int b[3]; // Ok: Create array of integers with default values of zero //b = a; // Error: Assignment operator does not work on arrays for (int i = 0; i < 3; ++i) // Ok: After this, b will now "equal" a b[i] = a[i];

Notice how the first array was initialized with values 1,2,3. C++ allows this for our array variable, but only once during the variable's declaration.

The usual way of iterating through an array is to use a counting variable (such as int i) within a for loop. You can also use pointers to iterate over an array's elements. Here is an alternative way of copying a's elements to b's elements:

int *apfirst, *aplast, *bp; apfirst = begin(a); aplast = end(a); bp = begin(b); while (apfirst != aplast) *bp++ = *apfirst++;

If you include <iterator>, you can use the begin function to get a pointer to the first element of an array, and you can use the end function to get a pointer to the non-existant element that lies right past the last element in an array. The while loop that you see here uses the apfirst pointer to keep track of the current position in the array from where we are copying values from. We also have pointer bp which keeps track of the current element of array b which is where the next value coming from *apfirst will be copied to. The while loop stops when apfirst reaches aplast.

The built-in begin and end functions are for our convenience, the code:

apfirst = begin(a); aplast = end(a); bp = begin(b);

is equivalent to:

apfirst = &a[0]; aplast = &a[3]; bp = &b[0]

assuming that a and b are integer arrays of size 3.

Character arrays

I have taught students to use string literals like "abc"s instead of "abc", here is the difference between these two forms: "abc"s creates a value of type string, and "abc" creates a value which can be assigned to a variable of type char[].

It turns out that "abc" is not a string, but rather it is a character array. A character array is to a string as an integer array is to an integer vector. A character array can initially store the same content as a string can; but, unlike strings, character arrays cannot concatenate additional content past it's own capacity. Character arrays do not have member functions and none of the operators work like those supported by string except for the subscript operator.

Despite the limitations of character arrays, strings (as well as the rest of the standard library components) are completely compatible with them. You can assign a character array to a string, but not the other way around. You can compare a string to a character array, but not vice versa. You can concatenate a character array to a string, but you cannot concatenate a string to a character array.

Before dynamic strings were invented, a character array was known as a "string". In C++, since the introduction of an official string data type, character arrays are also known as "c-string" or "cstring" (Named based on the older programming language that precedes C++).