I’m implementing a binary heap class. The heap is implemented as an array that is dynamically allocated. The heap class has members capacity, size and a pointer to an array, as:
class Heap
{
private:
Heap* H;
int capacity; //Size of the array.
int size; //Number of elements currently in the array
ElementType* Elements; //Pointer to the array of size (capacity+1)
//I've omitted the rest of the class.
};
My construcor looks like this:
Heap::Heap (int maxElements)
{
H = ( Heap* ) malloc ( sizeof ( Heap ) );
H -> Elements = ( ElementType* ) malloc ( ( maxElements+1 )*sizeof ( ElementType ) );
H -> Elements[0] = DUMMY_VALUE; //Dummy value
H -> capacity = maxElements;
H -> size = 0;
}
Since I’m mallocing twice and dereferencing both pointers in the constructor, I should check whether it succeeds. But what should I do if it fails? The constructor can’t itself return anything to indicate that it failed. Is it good programming practice to avoid mallocs in constructors altogether?
First of all, you do not need a
Heap*member variable inside yourHeapobject, and you certainly should not be allocating memory for it in theHeapconstructor – that’s just asking for trouble. Nor should you be accessing your member variables asH->Elements, but rather simply asElements.The only thing you need to allocate is the
Elementsarray.With regards to handling allocation failures, constructors should indicate failures via an exception. There is even a standard exception type,
std::bad_allocthat is usually used to indicate a failure to allocate memory.For example:
Even better, use
newrather thanmallocto allocate the memory.newwill automatically throw an exception of typestd::bad_allocif it fails to allocate memory.Example:
Note: if you use
newto allocate the object, you must usedeleteto free it rather thanfree. (Correction: In the example above, you are using the array form of new,new[], so you should call the array form of delete,delete[]).Finally, you haven’t shown how
ElementTypeis declared, but if it’s a type that has a non-default constructor/destructor (or if it’s a template parameter which means it can potentially be such a type), you have to usenewrather thanmallocwhen allocating it becausemallocwill not call the constructor (andfreewill not call the destructor). In general, it’s good practice to just always usenewanddeletein C++ rather thanmallocandfree.