Malloc in constructors
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 val开发者_JAVA技巧ue
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 your Heap
object, and you certainly should not be allocating memory for it in the Heap
constructor - that's just asking for trouble. Nor should you be accessing your member variables as H->Elements
, but rather simply as Elements
.
The only thing you need to allocate is the Elements
array.
With regards to handling allocation failures, constructors should indicate failures via an exception. There is even a standard exception type, std::bad_alloc
that is usually used to indicate a failure to allocate memory.
For example:
#include <stdexcept> // for std::bad_alloc
...
Heap::Heap (int maxElements)
{
Elements = ( ElementType* ) malloc ( ( maxElements+1 )*sizeof ( ElementType ) );
if (Elements == NULL)
throw std::bad_alloc("Failed to allocate memory");
...
}
Even better, use new
rather than malloc
to allocate the memory. new
will automatically throw an exception of type std::bad_alloc
if it fails to allocate memory.
Example:
Heap::Heap (int maxElements)
{
Elements = new ElementType[maxElements + 1]; // throws std::bad_alloc on failure
...
}
Note: if you use new
to allocate the object, you must use delete
to free it rather than free
. (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 ElementType
is 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 use new
rather than malloc
when allocating it because malloc
will not call the constructor (and free
will not call the destructor). In general, it's good practice to just always use new
and delete
in C++ rather than malloc
and free
.
You should learn some basic C++ 'rules of the road', the first of which is:
Use the Standard Template Library!
class Heap {
private:
std::vector<ElementType> elements;
}
And your constructor? You don't need one.
In general, any use of malloc()
or free()
in C++ is a 'code smell'. It's a sure-fire way of ending up with incorrectly constructed objects, buffer overflows, and memory leaks. Use new
and delete
, preferably with smart pointers.
Or, better yet. just have your objects constructed statically whenever possible.
You're allocating the object in its own constructor? Doesn't make sense:
H = ( Heap* ) malloc ( sizeof ( Heap ) );
Constructor is called by the new
operator, right after the memory allocation. If you're trying to create a singleton - use a static method which will instantiate the object, and call
class Heap{
public:
static Heap* Get();
private:
Heap();
static Heap* H;
}
Heap *Heap::H = 0;
Heap * Heap::Get()
{
if (!H)
H = new (Heap);
return H;
}
Heap::Heap()
{
// whatever else
}
To your question: malloc
is a C function. In C++ - use new
. You don't need to check for return values then, new
will throw exception on failure.
精彩评论