next up previous
Next: Improvements: Code placement Up: Simple Classes: myvector.h Previous: Simple vector class

Improvements: Overloaded assignment operator

Next we would like to add some arithmetic capabilities to our vector class. Most basic is the ability to assign a vector to another, as in

   vector a(10), b(10);
   a = b;
If we don't define the assignment method, the compiler uses a default method: it just copies the members, in this case, size and vec. That is not good for two reasons. First, by replacing a's value of vec with b's value, it makes the originally allocated storage for the elements of a inaccessible. Second, by making the vec the same, it is certainly true that a[i] becomes equal to b[i], since they are really now one and the same. But if we later change b[3], say, that also changes a[3] stealthily. And if we destroy a all of b's values are also trashed. A very unwise programming style! So we define an assignment operator that copies the elements of b to a. That way the assignment of vectors has the same meaning as for scalars (ordinary single values). With vectors we need to watch out for the possibility that a and b have different lengths. For now, we do a panic stop if the sizes don't match exactly.

Here is how we code a proper assignment operator:

class vector{
  ...
 public:
  ...

  // Assignment =
  vector & operator=(const vector &v){
    if(size != v.size){
       cerr << "FATAL vector::operator(const vector &) size mismatch: " <<
          size << " " << v.size << "\n";
       exit(1);
    }
    for(int i = 0; i < size; i++)vec[i] = v.vec[i];
    return *this;
  }
};

Let's look at how this works, starting with the declaration:




  vector & operator=(const vector &v){

To begin to make sense of what is going on here, we first have to observe that the assignment function operator= is declared inside the class declaration so it is a class function or method. Please compare it with the addition function operator+ for the complex class, which was defined outside the class and simply acted on two members of the class. The statement a = b is therefore interpreted by the compiler as a.operator=(b). The latter syntax emphasizes that the assignment is regarded as the operator= method of the instance a, taking the rhs as its argument. To allow for vector valued expressions on the rhs we must declare it const and for efficiency we pass it by reference.


    if(size != v.size)

Here we verify that the sizes match. Since in translating a = b the assignment takes place as a method in the instance a, the variable size refers to a.size and v.size refers to b.size.




    for(int i = 0; i < size; i++)vec[i] = v.vec[i];

By the same token for the example a = b the variable vec refers to a.vec and v.vec refers to b.vec.

The int i = 0 declares and initializes i. This declaration has a scope only through the end of the for block, which in this case is just the one line.




    return *this;

Now comes a bizarre point. Why did we need to give the assignment operator the type vector and have it return anything at all? Couldn't we have made it type void? After all, once we have copied in all the values, it would seem we are finished. The answer is, we might like to be able to write |a = b = c| for vectors, just as we do for scalars. In that case the assignment takes place in two steps. The result of assigning c to b is then assigned to a. The assignment chain is equivalent to a = b.operator=(c). Now we see that the result has to be of type vector in order for the final assignment to be meaningful. So the return value has to be the class object itself whose elements were just assigned. But the name of the class instance itself is not known inside the class. For the result of b = c we can't say return b in the code, because the same code has to work for a = b where we should return a instead. C++ solves this problem by making the special name this be a pointer to the class instance itself. Perhaps myself would have been a more descriptive choice than this, but the latter is the language. The star in front of this dereferences the pointer, making it the whole object itself, so finally the return value is a reference to the object itself whose values were just assigned.


next up previous
Next: Improvements: Code placement Up: Simple Classes: myvector.h Previous: Simple vector class
Carleton DeTar 2007-08-17