Implementing a Vector in C++: Working Smarter, Not Harder

You may remember when I created a vector in C. Yep, just another day in the life… How about we re-invent this wheel again?

This time we’ll be creating a vector in C++. This is much easier to do in C++ thanks to generics and operator overloading. Since this is a template class, we’ll be implementing the class in our .h file, forgoing the .cpp file. First we declare our class. Ensure that you declare it a template class.

namespace clt {
namespace dmp {

template <typename T>
class vector {

..words..

};
}
}

Remember namespaces? Gotta have those namespaces. Aside from that, nothing particularly special about this block. Next I’ll go over the methods and members of this class.

First up: our destructor. Nothing special going on here, we’re just going to delete our array pointer to ensure proper Resource Acquisition is Initialization (RAII). We’re going to let it be virtual to allow for subclassing.

virtual ~vector()
{
delete [] backing_array;
}

Next I’ll discuss the private method: initialize(). This method is called by all constructors and does 3 things: sets backing_array_size, resize_increment, and news up our array:

void initialize(const unsigned size, const unsigned increment)
{
backing_array_size = size;
resize_increment = increment;
backing_array = new T[backing_array_size];
}

Next up is our default constructor. It sets size and increment to 10. I like 10, it’s a nice, noble number. The kind of number you’d bring home to Mom and Dad:

vector()
{
initialize(10, 10);
}

Next we’ll talk about a private method: array_copy(). This method does pretty much what it says: it iterates through the original array and copies its contents into the new array:

void array_copy(T * orig_array, T * new_array)
{
for (int count = 0; count < backing_array_size; count++)
{
new_array[count] = orig_array[count];
}
}

Next to talk about is our copy constructor. It initializes the new vector with the old vector’s size and increment, then calls array_copy:

vector(const vector& orig)
{
initialize(orig.backing_array_size, orig.resize_increment);
array_copy(orig.backing_array, backing_array);
}

Moving along to operator=, which basically functions the same as the copy constructor, aside from the obligatory return statement:

vector& operator=(const vector& orig)
{
initialize(orig.backing_array_size, orig.resize_increment);
array_copy(orig.backing_array, backing_array);
return * this;
}

Next up: resize(). This private method creates a new T array sized backing_array_size+resize_increment. Then, it calls array_copy to copy the contents of the old array to the new. Finally, it increments backing_array_size by resize_increment, calls delete [] on backing_array, and sets backing_array to the new array:

void resize()
{
T * new_b_a = new T[backing_array_size + resize_increment];
array_copy(backing_array, new_b_a);
backing_array_size = backing_array_size + resize_increment;
delete [] backing_array;
backing_array = new_b_a;
}

Which brings us to operator[]. This method indexes into backing_array. If to_get >= size, it calls resize() until to_get is a valid index. It should be noted that this method does not prevent you from attempting to read into a null pointer:

T& operator[](const unsigned to_get)
{
while (to_get >= backing_array_size)
{
resize();
}
return backing_array[to_get];
}

Finally, we have a setter for resize_increment and a getter for backing_array_size:

void set_resize_increment(const unsigned to_set)
{
resize_increment = to_set;
}

const unsigned size()
{
return backing_array_size;
}

Lastly, this class has 3 private fields: a pointer array to the contents of the vector, the size of the array, and the resize increment:

T * backing_array;
unsigned backing_array_size;
unsigned resize_increment;

…and that’s all there is to it. No casting void pointers, no manual resource allocation, and no unweildly method names. Or you could just use std::vector I guess, but what would be the fun in that?

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: