Sunday, April 15, 2012

Elegant Copy Constructors and Assignment Operators

So recently I discussed the importance of adhering to the Orthodox Canonical Class Form, and in this previous week in class I learned of a very elegant way to complete two of these: the copy constructor and the assignment operator. As long as you are careful, these two methods can often be very simple to write and do not typically require a large amount of thought. Most problems arise when there are pointer variables as fields in a class. Using the default assignment operator will simply copy the address of the pointer over which results in two variables pointing to the same address. Honestly, I am having trouble recalling how I used to do this because this new method I have learned of completing these two tasks as nullified all of my old practices.

So let's say we have this class, my_object, and in this class we have only an int and an int* as private data fields for the class, like so: (Yes, it is stupid, but I am simply trying to show a point).

class my_object {
    private:
        int x;
        int* y;
};

Now, we do not want the default copy constructor or assignment operator, because they will both result in some nasty pointer bugs. We want each instance of my_object to have its own value of y, and more importantly a unique address for y! So, we will continue on to create the copy constructor using C++'s interesting syntax for initializing variables in the method declaration:

my_object::my_object(const my_object& that) : x(that.x), y(new int) {
    *y = that->y;
}

Notice that I accepted that as a reference, and that I simply initialized this->x to that.x, and that I created a new int on the heap and set its value to the value of that's y in the method body. How can we write an assignment operator that takes advantage of the copy constructor we just created? I would argue that this can be done precisely how Professor Downing enlightened me in class. First I will show it here and see if you can figure it out:

my_object::my_object& operator = (my_object that) {
    std::swap(x, that.x);
    std::swap(y, that.y);
    return *this;
}

In the words of Dr. Downing, "Beautiful!". Really, I truly believe this is a beautiful solution. We created the copy constructor that took care of the pointer copy issue, and simply passed the my_object by value in the assignment operator such that a correct copy is created, and we can swap the variables out of the object to get the proper assignment.

No comments:

Post a Comment