We looked at dynamic memory in C last week, so let’s compare it with dynamic memory in C++.
Allocation
In C++, if you want to allocate on the heap rather than the stack, you need to use the new operator.
Just like the C equivalents, the new operator returns a void* pointer to the block of memory that has been allocated.
There are two versions of new, the first returns a single item:
int* x; x = new int;
The second, using square brackets, returns an array of items:
int* x; x = new int[16];
Checking for success
C allocators return NULL and set errno when they fail, which you should explicitly check for.
In C++ however, an exception is thrown (bad_alloc). If you don’t have the code in place to catch the exception, your program will terminate.
You can force C++ to behave like C by passing the nothrow argument to new:
int* x; x = new(nothrow) int;
Now new will behave like a C function and set x to NULL if it fails.
Of course, if you do this, you’ll remember check for a NULL value before using the pointer, won’t you?
Clearing up
Just like in C, you MUST remember to clear up after yourself when you’ve spent the afternoon happily declaring memory on the heap.
To do this, you need to call delete. There are two versions of delete that match the two versions of new:
//for single objects delete x;
//for arrays delete[] x;
What if you use the wrong one?
If you forget to use the brackets on an allocated array, you will only delete the first element. The others will remain inaccessible in memory, causing a memory leak. And you don’t want that to happen, do you?
If you use the bracketed version on a single object the behaviour is undefined. Which, if you’re unsure, means you can’t rely on the result to be anything you might expect 🙂
Can you mix and match between new, malloc, delete and free?
No. Never do this!
First off, it’s just plain wrong to mix functionality from two separate languages (even though you can).
Second, new and delete are used in C++ because they call the constructor and destructor of an object respectively. The C equivalents, malloc and free do not do this.
So, if you create an object with malloc, any work done in the constructor will not happen.
Worse, if you free an object that was allocated with new (instead of using delete), the object’s destructor is not called. If your object uses memory dynamically and the destructor does the clearing up, then what will you have? Yes, a memory leak.
But that won’t happen to you now, because you’ve just read this, right? 😉
This is great, Faye. A mention to smart pointers as the recommended way to deal with dynamic memory in C++11 (the latest version) would have been recommended, agree? http://ootips.org/yonat/4dev/smart-pointers.html
Yes absolutely – thanks for posting the link. However, this seems to refer to std::auto_ptr, which is deprecated in C++11 (it now uses shared_ptr and unique_ptr).
I’m planning some C++11 articles in the new year, but you’re right that it should really have been mentioned above 🙂