11.7. operator[]

Time: 00:03:44 | Download: Large, Large (CC), Small | Streaming, Streaming (CC) | Slides (PDF)
Review

Understanding and using the index operator rests on concepts and terminology introduced previously. Please review the following as needed:

Previous chapters demonstrated using a square bracket pair to index into arrays and C-strings. Despite their frequent appearance in programs, it's easy to ignore that the brackets form an operator. The index operator performs a relatively straightforward address calculation.

char message[100]; char c = message[10]; message[10] = 'X';
(a)(b)(c)
The fundamental or original index operator. The index operator, [], does relatively simple address arithmetic, calculating the address of an array element. The operator takes two operands: the left-hand is an address, and the right-hand is an integer. From these values, it calculates the memory address of an array element.
  1. The definition statement creates a one-dimensional character array whose size is 10 and whose name is message. Although this notation is intrinsic or built-in to the compiler, it's another example of an operator with multiple meanings - like the asterisk - and is not the index operator.
  2. Accesses element 10 in the message array; used on the right-hand side of the assignment operator, message[10] is an r-value.
  3. Accesses element 10 in the message array; used on the left-hand side of the assignment operator, message[10] is an l-value
message is the name of an array. In parts (b) and (c), an array's name is its address, becoming the index operator's left-hand operand. The value 10, the index location of one array element, becomes the right-hand operand. The compiler calculates the element's memory address with relatively simple address arithmetic: When evaluated, the expression is the address of the 11th element, counting from 0, in the array. When the program uses the address to get the value stored at that memory location, the address is an r-value. But if the program uses the address to store a new value at that memory location, the address is an l-value.

The text also presented the index operator as one way (along with the at function) to access the characters in an instance of the C++ string class, suggesting that programmers can overload it for new classes exhibiting some array structure. The following example assumes that we are creating a new class named LPString.

class LPString
{
    private:
	char array[255];

    public:
		. . .
	char& operator[](int index);
};
char& LPString::operator[](int index)
{
    if (index > 0 && index <= array[0])
        return array[index];
    else
        throw "Index out of bounds exception";
}
 
 
(a)(b)
Overloading operator[]. We initially created the LPString example, which implements length-prefix strings (also known as Pascal or UCSD strings) in the Classes and Objects chapter. It is relatively easy to add an overloaded index operator to the example.
  1. A partial LPString class: array is the name of an array of characters storing the string's characters. The first byte or character of array (that is, array[0]) is reserved to store the string's length.
  2. The overloaded operator[] verifies that the index value is within bounds, throwing an exception if it isn't. Given a valid index, the operator calculates and returns a reference to the indexed element. It's crucial to recognize that the function return must be by reference, as this allows the operator to form an l-value.
LPString::LPString(const char* s)
{
		. . .
	array[i + 1] = s[i];
		. . .
}
LPString	message;

char x = message[5];
message[5] = 'A';


(a)(b)
Fundamental vs. overloaded index operators. The square brackets, [], form the index operator for fundamental types and classes. Furthermore, the brackets can appear in the same program, making it vital for programmers to distinguish between them.
  1. The LPString functions rely heavily on the fundamental index operator, illustrated by the LPString conversion constructor.
  2. Once the LPString class overloads the index operator, any program using LPStrings can use it.
Programs using the LPString class now have two versions of the index operator: the original or fundamental version and the programmer-created overloaded version. Like any overloaded function, the compiler uses the arguments to select the correct function to call. In the case of operator[], the left-hand operand becomes the distinguishing argument. For example, programs index C-string s and the character array array with the fundamental index operator (coral), and the LPString message with the overloaded LPString index operator (light blue).