Constructors and Destructors in C++ – Part 3

We’ve talked a lot about how construction and destruction work. Now, finally, it’s time to see how they go wrong. Firstly, let’s say that an object is being constructed and an exception is thrown. In this situation the classes destructor is not called. This, in general, should not be a problem. The only exception throwing code you should have in a constructor is code that manages some resource. And, you should manage at most one resource per class. So if an exception is thrown in your constructor, it means that the resource you are managing has not been setup and so the destructor does not need to be called.

So if we have a class like this:

class Base
{
public:
	Base()
	{
		std::cout << "Base Constructor" << std::endl;
		throw std::exception();
	}

	virtual ~Base()
	{
		std::cout << "Base Destructor" << std::endl;
	}
};

and we run the following main function,

int main()
{
    try
    {
        Base baseObject;
    }
    catch(std::exception& e)
    {
        std::cout << "Exception caught" << std::endl;
    }
    return 0;
}

we will see:

Base Constructor
Exception caught

As you see, no calls to the destructor. Now suppose, with the same main function, we throw an exception from a derived class like so,

class Base
{
public:
	Base()
	{
		std::cout << "Base Constructor" << std::endl;
	}

	virtual ~Base()
	{
		std::cout << "Base Destructor" << std::endl;
	}
};

class Derived : public Base
{
public:
	Derived() : Base()
	{
		std::cout << "Derived Constructor" << std::endl;
		throw std::exception();
	}

	Derived(int i)
	{
		std::cout << "Derived with parameter Constructor" << std::endl;
	}

	virtual ~Derived()
	{
		std::cout << "Derived Destructor" << std::endl;
	}
};

Then we will see:

Base Constructor
Derived Constructor
Base Destructor
Exception caught

The Derived destructor is not called, but the Base Destructor is. This is because by the time the exception is thrown in the Derived class, we have completely the construction of the Base class, so that will need to be destroyed as normal.

Local objects that are constructed within the constructor will be destroyed as normal when an exception is thrown. So, for example code like this:

class Simple
{
public:
	Simple()
	{
		std::cout << "Simple Constructor" << std::endl;
	}

	virtual ~Simple()
	{
		std::cout << "Simple Destructor" << std::endl;
	}
};

class Basic
{
public:
	Basic()
	{
		std::cout << "Basic Constructor" << std::endl;
                Simple simpleObject;
		throw std::exception();
	}

	virtual ~Basic()
	{
		std::cout << "Basic Destructor" << std::endl;
	}
};

when executed via,

int main()
{
	try
	{
		Basic basicObject;
	}
	catch(std::exception& e)
	{
		std::cout << "Exception caught" << std::endl;
	}
	return 0;
}

will produce:

Basic Constructor
Simple Constructor
Simple Destructor
Exception caught

So, as we have seen, you can throw exceptions from the constructor. You cannot however throw an exception from a destructor. Try building the following code,

class Simple
{
public:
	Simple()
	{
		std::cout << "Simple Constructor" << std::endl;
	}

	virtual ~Simple()
	{
		std::cout << "Simple Destructor" << std::endl;
                throw std::exception();
	}
};

You should get a warn telling you that destructors are “noexcept” in C++. If you run this code as before, you will get:

Simple Constructor
Simple Destructor
terminate called after throwing an instance of 'std::exception'
  what():  std::exception
Aborted (core dumped)

C++ will always terminate when an exception like this is thrown in a destructor. The reason is simple. Suppose we throw an exception and then start unwinding the stack. If, when we destroy an object on the stack it’s destructor threw another exception, there is no way to catch both exceptions. We cannot catch one exception and abandon the other, so the program gives up and terminates whenever an exception is thrown in a destructor.

Constructors and Destructors in C++ – Part 2

In our previous post we discussed constructors and destructors for local objects. Now, suppose we have the same hierarchy of classes, Base, Derived and DerivedAgain, and we constructed a DerivedAgain object the heap, like so:

int main()
{
    DerivedAgain* derivedAgainObject = new DerivedAgainObject();
    return 0;
}

When we run this we will see the following,

Base Constructor
Derived Constructor
DerivedAgain Constructor

The constructors were called in the same order as before. However, because our DerivedAgain object was created on the heap the destructor was never called. If we want to destroy our object we must explicitly use delete.

int main()
{
    DerivedAgain* derivedAgainObject = new DerivedAgainObject();
    delete derivedAgainObject;
    return 0;
}

The above will output the following to the command line,

Base Constructor
Derived Constructor 
DerivedAgain Constructor
DerivedAgain Destructor
Derived Destructor
Base Destructor

Let’s consider what happens when we have a pointer of type Derived that points to an object of typed DerivedAgain. Say we run:

Derived* derivedPointer = new DerivedAgain();
delete derivedPointer;
return 0;

When we run this code we will see:

Base Constructor
Derived Constructor
DerivedAgain Constructor
Derived Destructor
Base Destructor

The constructors are the same, because we are creating a DerivedAgain object as before. However, now we are calling delete on a pointer of type Derived. So only the Derived and Base class destructors are called.

We can avoid this problem by making our destructors virtual.

class Base
{
public:
        Base()
        {
                std::cout << "Base Constructor" << std::endl;
        }

        virtual ~Base()
        {
                std::cout << "Base Destructor" << std::endl;
        }
};

class Derived : public Base
{
public:
        Derived() : Base()
        {
                std::cout << "Derived Constructor" << std::endl;
        }

        virtual ~Derived()
        {
                std::cout << "Derived Destructor" << std::endl;
        }
};

class DerivedAgain : public Derived
{
public:
        DerivedAgain() : Derived()
        {
                std::cout << "DerivedAgain Constructor" << std::endl;
        }

        ~DerivedAgain()
        {
                std::cout << "DerivedAgain Destructor" << std::endl;
        }
};

Now when we run,

int main()
{
        Derived* derivedPointer = new DerivedAgain();
        delete derivedPointer;
        return 0;
}

we will see:

Base Constructor
Derived Constructor
DerivedAgain Constructor
DerivedAgain Destructor
Derived Destructor
Base Destructor

Even though we have a pointer of type Derived, because the destructor is virtual, when we call delete, the DerivedAgain destructor gets called. What’s interesting here, is that we always call all the destructors upwards through the type hierarchy, the use of virtual ensures that we start at the right level. For this reason, we should usually make our destructors virtual.

We can even make our destructors pure virtual. However, we will have to give this pure virtual destructor a body. It is a common misconception that a pure virtual function necessarily can’t have a body, this is not true. However pure virtual destructors are probably one of the only examples of when you would want to do it. The only reason we would want to make a destructor pure virtual is that we want to make a class abstract and the destructor is the only method. In my opinion this is a very unlikely to happen, so it’s not something we should really worry about.

In the next post we will have a look at what happens when things go wrong in construction and destruction.

Constructors and Destructors in C++ – Part 1

We’re going to think a little bit about constructing and destroying objects in C++. Let’s say we have three very simple classes, Base, Derived and DerivedAgain.

class Base
{
public:
	Base()
	{
		std::cout << "Base Constructor" << std::endl;
	}

	~Base()
	{
		std::cout << "Base Destructor" << std::endl;
	}
};

class Derived : public Base
{
public:
	Derived()
	{
		std::cout << "Derived Constructor" << std::endl;
	}

	~Derived()
	{
		std::cout << "Derived Destructor" << std::endl;
	}
};

class DerivedAgain : public Derived
{
public:
	DerivedAgain()
	{
		std::cout << "DerivedAgain Constructor" << std::endl;
	}

	~DerivedAgain()
	{
		std::cout << "DerivedAgain Destructor" << std::endl;
	}
};

Now suppose we run the following code,

int main()
{
	DerivedAgain derivedAgainObject;
	return 0;
}

The output will be:

Base Constructor
Derived Constructor 
DerivedAgain Constructor
DerivedAgain Destructor
Derived Destructor
Base Destructor

Why is this? Well, to construct the DerivedAgain object, first we must construct aDerived object and to construct a Derived object, first we must construct a Base object. Similarly, when the object goes out of scope, to destroy it, first the DerivedAgain destructor is called, then the Derived destructor and then the Base Destructor. So, when creating an object we step down through the inheritance hierarchy, and when destroying it we step back up through the hierarchy.

We can call these constructors explicitly. Indeed the above code is exactly quivalent to:

class Base
{
public:
	Base()
	{
		std::cout << "Base Constructor" << std::endl;
	}

	~Base()
	{
		std::cout << "Base Destructor" << std::endl;
	}
};

class Derived : public Base
{
public:
	Derived() : Base()
	{
		std::cout << "Derived Constructor" << std::endl;
	}

	~Derived()
	{
		std::cout << "Derived Destructor" << std::endl;
	}
};

class DerivedAgain : public Derived
{
public:
	DerivedAgain() : Derived()
	{
		std::cout << "DerivedAgain Constructor" << std::endl;
	}

	~DerivedAgain()
	{
		std::cout << "DerivedAgain Destructor" << std::endl;
	}
};

Let’s change things up a little bit, suppose we have the following situation.

class Derived : public Base
{
public:
	Derived()
	{
		std::cout << "Derived Constructor" << std::endl;
	}

	Derived(int i)
	{
		std::cout << "Derived Constructor With Parameter" << std::endl;
	}

	~Derived()
	{
		std::cout << "Derived Destructor" << std::endl;
	}
};

class DerivedAgain : public Derived
{
public:
	DerivedAgain() : Derived(5)
	{
		std::cout << "DerivedAgain Constructor" << std::endl;
	}

	~DerivedAgain()
	{
		std::cout << "DerivedAgain Destructor" << std::endl;
	}
};

Now we are explicitly calling a non-default constructor from the Derived class. All the other implicit calls to default constructors remain the same. When we run the main function as before, we will see:

Base Constructor
Derived Constructor with parameter Constructor
DerivedAgain Constructor
DerivedAgain Destructor
Derived Destructor
Base Destructor

You cannot however do something like this:

class DerivedAgain : public Derived
{
public:
	DerivedAgain() : Base()
	{
		std::cout << "DerivedAgain Constructor" << std::endl;
	}

	~DerivedAgain()
	{
		std::cout << "DerivedAgain Destructor" << std::endl;
	}
};

Here, we are trying to call the Base constructor from the DerivedAgain class. This will not compile, we can only call constructors from the classes that we directly inherit from.

So far we have only looked at constructors and destructors for local objects, that is, without using the new keyword. In part 2, we will look at what happens when we construct and destroy objects dynamically.

RAII in C#

We’ve already discussed RAII in C++, now it’s time to see how we implement the same pattern in C#. We don’t manage our memory in C#, however we still need to manage other resources, like network and database conections, files and mutexes. In C++, whenever control leaves a block, the local objects defined in that block are destroyed. In C# this is not the case because the runtime uses garbage collection to manage memory. This means that the runtime periodically looks for objects that are no long referenced and deletes those that it finds. So, unfortunately, we cannot use the same trick manage resources.

In order to guarantee that a resource is released in C# we can use a finally block like so:

// acquire a resource
try
{
   // use resource and do other stuff as well
}
finally
{
   // release resource
}

A finally block will be executed whenever control leaves the try block, either because it reaches the end of the block, it reaches a return statement of an exception is thrown.

We can also encapsulate resource management with a class like in C++. In C# we normally do this by implementing the IDisposable interface. The IDisposable interface looks like this:

interface IDisposable
{
    void Dispose();
}

We acquire the resource in the constructor and we release the resource in the Dispose method.

class ResourceHolder : IDisposable
{
   public ResourceHolder()
   {
       // acquire resource here
   }

   public void Dispose()
   {
       // release resource
   }
}

The Dispose method of our ResourceHolder must be called. It does not happen automatically like a destructor in C++. We can combine a class implementing IDisposable with the finally block like this:

var holder = ResourceHolder()
try
{
   // use resource and do other stuff as well
}
finally
{
   holder.Dispose();
}

In fact, this pattern is so useful that some syntactic sugar exists for it, the using statement.

using(var holder = ResourceHolder())
{
   // use resource and do other stuff as well
}

The above code is exactly equivalent to our previous code example with an explicit finally block. Whenever control exits the using block, the Dispose method of the object declared inside the using statement is called.

RAII is a great example of something that ends up being more complicated in C# than it is in C++. Usually, things are easier in C#!

RAII in C++

When we are programming, we often have to deal with resources. A resource is some system functionality of limited availability, that we have to manage explicitly. This means that before we use it we have to acquire it and when we are finished we have to release it.

Examples of resources are:

  • Memory on the heap, we acquire memory on the heap with the new keyword and we must release it with the delete keyword.
  • Files, we acquire a file handle by asking the operating system to open the file, and we release it by asking for the file to be closed.
  • Mutexes, we acquire a mutex by locking it and we release a mutex by unlocking it.
  • Network or Database connections, these will have their own specific acquisition and release logic, and will usually require both.

So, let’s suppose we are using a file, and our code looks a little something like this:

public void DoSomeStuffWithAFile()
{
    ofstream file("output-file.bin");
    // do some stuff with this file
    // do some other stuff
    file.close();
}

Here, the file is our resource, we acquire it with the file constructor and we release it with the close method. However, suppose, somehow control returned from this method before we reached the final line: file.close();. Then we will not have released this resource. This can cause pretty serious problems, as resources are by definition, limited in their availability. If we use up all the file handles like this, eventually we won’t be able to open any more files!

There are two ways control could return without us using the close method. The first is that an exception is thrown somewhere between the creation of the file and the file.close() call. When this happens, control will leave the DoSomeStuffWithAFile and we will never close the file. If this exception is caught at a higher level, the file resource will be left open for the remaining duration of the program. It doesn’t really matter if an exception is thrown and not caught, because then the program will terminate and the operating system will release all the resources we held anyway.

The second is if we simply have a return statement somewhere in this method, something like:

public void DoSomeStuffWithAFile()
{
    ofstream file("output-file.bin");
    // do some stuff with this file
    if(/* some condition */)
    {
        return;
    }
    // do some other stuff
    file.close();
}

We should have a file.close() call before this return statement, but we could forget it.

How can we avoid this two potential sources of resource leakage? Well there is a pattern that handles both! This pattern is called Resource Acquisition is Initialisation. When an object is created on the stack, it is guaranteed to be torn down when control leaves the current block, as the stack is unwound. This happens whether control leaves by normal control flow or because of a thrown exception. So, we encapsulate resource acquisition and release in a class. In our example we would do something like:

class FileHolder
{
public:
    ofstream file;
    FileHolder(string fileName) : file(filename)
    {
    }

    ~FileHolder()
    {
        file.close();
    }
}

Then we use this FileHolder class like so:

public void DoSomeStuffWithAFile()
{
    FileHolder fileHolder("output-file.bin");
    // do some stuff with this file
    if(/* some condition */)
    {
        return;
    }
    // do some other stuff
}

Now, whenever control leaves the DoSomeStuffWithAFile function, the destructor will be called on the fileHolder object as the stack is unwound and the close method on our file will be called.

We can use the same pattern with any resource, we create a holder class that acquires the resource in the constructor and releases it in the destructor. That way, we are using the unwinding of the stack to control the release of our resources, which I think, is pretty cool.

In this example we have left our file object public. It would be better practice to make the internal file object private, and expose the methods we wish to use via methods on the FileHolder class. That way we control exactly how the file is used, in particular, we won’t be able to do this:

public void DoSomeStuffWithAFile()
{
    FileHolder fileHolder("output-file.bin");
    // do some stuff with this file
    fileHolder.file.close();
    // do some other stuff
}

The above code may cause our file to be closed twice, once explicitly and once as the stack is unwound. This isn’t necessarily a problem for files, but we should avoid it. For other resources, releasing twice might be a serious problem.

This pattern has other advantages. Firstly the code for acquiring and releasing it are kept together logically. Which makes the resource management logic clearer and easier to maintain. Secondly it reduces code duplication as we do not need to explicitly acquire and release a resource every time we use it.

For some resources, RAII is implemented in C++ for us already. The two most common examples are lock_guard which managers a mutex and smart pointers which manage memory.