Aug 26

A C++ compiler implicitly creates a copy constructor and an assignment operator for any class that does not explicitly define them.

class Widget
{
public:
    Widget( Gadget* gadget )
    : gadget_( gadget ) {}

    ~Widget() { delete gadget_; }

private:
    Gagdet* gadget_;
};

 
Here, we have not explicitly defined the copy constructor or the assignment operator, so the compiler will add them, resulting a class like this:

class Widget
{
public:
    Widget( Gadget* gadget )
    : gadget_( gadget ) {}

    ~Widget() { delete gadget_; }

    Widget( const Widget& widget )
    : gadget_( widget.gadget_ ) {}

    Widget& operator=( const Widget& widget )
    {
        gadget_ = widget.gadget_;
        return *this;
    }

private:
    Gagdet* gadget_;
};

 
Consider the following code fragment that uses the Widget class:

int main()
{
    Gadget* gadget = new Gadget;
    Widget* w1 = new Widget( gadget );

    Widget w2 = *w1;    // Copy using the assignment operator
    Widget w3( *w1 );   // Copy using the copy constructor

    return 0;
}

 
The default copy constructor and assignment operator copy all member variables from an object to another as-is. The problem arises when an object has a pointer to some other object; gadget_ in this case. When copying or assigning an object using the automatically generated functions, only the pointer value is copied. Both the objects’ member variables now point to the same object. Now, when the original object is destroyed, it deletes the widget_ member object whose pointer it held. The result is that the copied object’s pointer now points to deleted memory, and all bets are off.

When you have classes that contain pointers to other objects, consider if it is ok to just copy the pointers using the automatically generated copy constructor and assignment operator. If the pointed-to object ownership is not within the objects being copied, memberwise copying using the default copy constructor and copy assignment is ok. But it the objects own the data behind the pointers, you’ll want to either disable the copy constructor and assignment operator (by making them protected/private), or make sure the object is actually cloned (or deep-copied) so that the new object is self-contained. This means that the pointers cannot point to the same objects but new ones instead, which are created upon cloning the object in the copy constructor or assignment operator.

Aug 22

This post concerns something that has bothered me for years. Namely, the tendency of people to write their code using as few keystrokes as possible. While there’s often nothing to gain, there’s a lot to lose, two major issues being readability and debuggability. While reading this post may be akin to drinking poison to some of you (and you know who you are!), your fellow developers will thank you when they are wading through your code.

Depending on the environment you’re using, run-time debug information may be available to you in several ways. Since I have most experience with the Eclipse/Carbide IDE, the debuggability part of post will be primarily applicable to that environment, but it’ll likely apply just as well to most other IDEs. The readability part of course applies no matter what environment you’re using.

Consider the following fragment of code:

int i = 5;

When you’re running this on a debugger, you’re able to see that the value of a variable named ‘i’ is 5. (It often happens that the compiler optimizes out unused variables even in debug builds, so you may need to write some superfluous statement (such as logging) where you use such an otherwise unused variable in order to be able to see it in the debugger, but I digress.) This is all well and good, but consider the following example:

Base* b = ptrGadget->DoStuff(item).Factor()[index];

Here, some IDEs are able to tell you what kind of an object the DoStuff() and Factor() functions return. You’d still have to hover your mouse over the function names (or step into the code), which is basically extra work for you every single time you forget the return types. Considering the amount of information you have to juggle in your mind while debugging, this soon becomes a real frustration. Additionally, from a readability standpoint, let’s consider how a developer new to the project (or you after a 5-week vacation) sees this:

“We’re apparently trying to get a pointer to a class named Base (might be a virtual base class, mind you) by calling a method named DoStuff() on the ptrGadget pointer. The function takes as parameter a variable called item and returns some object (by value or reference?), on which we then call a function named Factor(). Finally, we take an element from an array(?) returned by the Factor() function and store it to the pointer b of the class named Base.”

The code works, but the problem for the person debugging the code is that a lot of details are hidden beneath the surface. For example, we cannot see just by looking at the code what kind of object the DoStuff() function returns. Neither do we see what kind of an array (or any type for which the subscript operator is defined) the Factor() function returns. Sure, you could step into the code using the debugger and have a look, but doing this every time after you forget the types in question gets old fast. Fortunately, the solution is simple and just as efficient.

For the solution, we just have to look up the types in the code being called once and write them as local (automatic) variables to our own code. For the sake of this example, let’s say you find out that the DoStuff() function returns a const reference to an object of class Charger (just picking words out of my immediate surroundings here). The Charger class has the Factor() function which returns an std::vector that contains Base class pointers.

const Charger& charger = ptrGadget->DoStuff(item);
std::vector<Base*> vecBase = charger.Factor();
Base* b = vecBase[index];

Now, we have divided our “neat” piece of code on one line to three. And to what gain? Well, we are now able to clearly see what types we are working on (Charger and std::vector<Base*>). These were hidden from the view previously. And although the code is on three lines and there’s more text, it is much more readable because now we have just a single statement per line instead of three. The debugger is also able to display information about the automatic variables we have created, namely charger and vecBase.

Naturally, you could replace the types used in this example with anything you like, and the point would still stand. The types I used where were from the top of my head and at some point I’ll probably replace them with others that better suit the example.

preload preload preload