Search

9.8 — Overloading the subscript operator

When working with arrays, we typically use the subscript operator ([]) to index specific elements of an array:

However, consider the following IntList class, which has a member variable that is an array:

Because the m_anList member variable is private, we can not access it directly from cMyList. This means we have no way to directly get or set values in the m_anList array. So how do we get or put elements into our list?

Without operator overloading, the typical method would be to create access functions:

While this works, it’s not particularly user friendly. Consider the following example:

Are we setting element 2 to the value 3, or element 3 to the value 2? Without seeing the definition of SetItem(), it’s simply not clear.

A better solution in this case is to overload the subscript operator ([]) to allow access to the elements of m_anList. The subscript operator is one of the operators that must be overloaded as a member function. In this case, our overloaded subscript will take one parameter, an integer value that is the index of the element to access, and it will return an integer.

Now, whenever we use the subscript operator ([]) on an object of our class, the compiler will return the corresponding element from the m_anList member variable! This allows us to both get and set values of m_anList directly:

In this case, it’s much more obvious that cMyList[2] = 3 is setting element 2 to the value of 3!

Why operator[] returns a reference

Let’s take a closer look at how cMyList[2] = 3 evaluates. Because the subscript operator has a higher precedence than the assignment operator, cMyList[2] evaluates first. cMyList[2] calls operator[], which we’ve defined to return a reference to cMyList.m_anList[2]. Because operator[] is returning a reference, it returns the actual cMyList.m_anList[2] array element. Our partially evaluated expression becomes cMyList.m_anList[2] = 3, which is a straightforward integer assignment.

In the lesson a first look at variables, you learned that any value on the left hand side of an assignment statement must be an l-value (which is a variable that has an actual memory address). Because the result of operator[] can be used on the left hand side of an assignment (eg. cMyList[2] = 3), the return value of operator[] must be an l-value. As it turns out, references are always l-values, because you can only take a reference of variables that have memory addresses. So by returning a reference, the compiler is satisfied that we are returning an l-value.

Consider what would happen if operator[] returned an integer by value instead of by reference. cMyList[2] would call operator[], which would return the value of cMyList.m_anList[2]. For example, if m_anList[2] had the value of 6, operator[] would return the value 6. cMyList[2] = 3 would partially evaluate to 6 = 3, which makes no sense! If you try to do this, the C++ compiler will complain:

C:VCProjectsTest.cpp(386) : error C2106: '=' : left operand must be l-value

Rule: Values returned by reference or pointer can be l-values or r-values. Values returned by value can only be r-values.

Conclusion

The subscript operator is typically overloaded to provide access to 1-dimensional array elements contained within a class. Because strings are typically implemented as arrays of characters, operator[] is often implemented in string classes to allow the user to access a single character of the string.

One other advantage of overloading the subscript operator is that we can make it safer than accessing arrays directly. Normally, when accessing arrays, the subscript operator does not check whether the index is valid. For example, the compiler will not complain about the following code:

However, if we know the size of our array, we can make our overloaded subscript operator check to ensure the index is within bounds:

In the above example, we have used the assert() function (included in the cassert header) to make sure our index is valid. If the expression inside the assert evaluates to false (which means the user passed in an invalid index), the program will terminate with an error message, which is much better than the alternative (corrupting memory). This is probably the most common method of doing error checking of this sort.

9.9 -- Overloading the parenthesis operator
Index
9.7 -- Overloading the increment and decrement operators

19 comments to 9.8 — Overloading the subscript operator

  • senjes

    What will happen when I have array of objects and the subscript operator overloaded. I tried it , It is trying to invoke the equal to operator which I feel is correct . In this case, If I have array of objects then the subscript operator overloading is ignored right. Is there any workaround for this ?

Leave a Reply

You can use these HTML tags

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">