- 18.1 Introduction
- 18.2 Initialization
- 18.3 Copying
- 18.4 Essential operations
- 18.5 Access to vector elements
- 18.6 Arrays
- 18.7 Examples: palindrome
- Drill
- Review
- Terms
- Exercises
- Postscript

## 18.5 Access to vector elements

So far (§17.6), we have used ** set()** and

**member functions to access elements. Such uses are verbose and ugly. We want our usual subscript notation:**

`get()`**. The way to get that is to define a member function called**

`v[i]`**. Here is our first (naive) try:**

`operator[]`class vector {int sz;//the sizedouble* elem;//a pointer to the elementspublic://. . .double operator[](int n) { return elem[n];} //return element};

That looks good and especially it looks simple, but unfortunately it is too simple. Letting the subscript operator (** operator[]()**) return a value enables reading but not writing of elements:

vector v(10);double x = v[2];//finev[3] = x;//error: v[3] is not an lvalue

Here, ** v[i]** is interpreted as a call

**, and that call returns the value of**

`v.operator[](i)`**’s element number**

`v`**. For this overly naive**

`i`**,**

`vector`**is a floating-point value, not a floating-point variable.**

`v[3]`Our next try is to let ** operator[]** return a pointer to the appropriate element:

class vector {int sz;//the sizedouble* elem;//a pointer to the elementspublic://. . .double* operator[](int n) { return &elem[n]; }//return pointer};

Given that definition, we can write

vector v(10);for (int i=0; i<v.size(); ++i) {//works, but still too ugly*v[i] = i;cout << *v[i];}

Here, ** v[i]** is interpreted as a call

**, and that call returns a pointer to**

`v.operator[](i)`**’s element number**

`v`**. The problem is that we have to write**

`i`**to dereference that pointer to get to the element. That’s almost as bad as having to write**

`*`**and**

`set()`**. Returning a reference from the subscript operator solves this problem:**

`get()`class vector {//. . .double& operator[ ](int n) { return elem[n]; }//return reference};

Now we can write

vector v(10);for (int i=0; i<v.size(); ++i) {//works!v[i] = i;//v[i] returns a reference element icout << v[i];}

We have achieved the conventional notation: ** v[i]** is interpreted as a call

**, and that returns a reference to**

`v.operator[](i)`**’s element number**

`v`**.**

`i`### 18.5.1 Overloading on `const`

The ** operator[]()** defined so far has a problem: it cannot be invoked for a

**. For example:**

`const vector`void f(const vector& cv){double d = cv[1];//error, but should be finecv[1] = 2.0;//error (as it should be)}

The reason is that our ** vector::operator[]()** could potentially change a

**. It doesn’t, but the compiler doesn’t know that because we “forgot” to tell it. The solution is to provide a version that is a**

`vector`**member function (see §9.7.4). That’s easily done:**

`const`class vector {//. . .double& operator[](int n);//for non-const vectorsdouble operator[](int n)const; //for const vectors};

We obviously couldn’t return a ** double&** from the

**version, so we returned a**

`const`**value. We could equally well have returned a**

`double`**, but since a**

`const double&`**is a small object there would be no point in returning a reference (§8.5.6), so we decided to pass it back by value. We can now write**

`double`void ff(const vector& cv, vector& v){double d = cv[1];//fine (uses the const [])cv[1] = 2.0;//error (uses the const [])double d = v[1];//fine (uses the non-const [])v[1] = 2.0;//fine (uses the non-const [])}

Since ** vectors** are often passed by

**reference, this**

`const`**version of**

`const`**is an essential addition.**

`operator[]()`