Reputation: 3500
There is no realloc
in C++; Of course you can always allocate a new block with new
, copy the old block to the new block, free the old block with delete
.
The problem is that realloc can often be faster than this - this happens when the memory block is re-sized 'in place' - that is the return value of realloc
happens to be the same as the argument pointer value; this also avoids the copying of memory from old block to new block.
What does the standard say - is one allowed to pass pointer returned by the global new
operator to realloc
? (in glibc both new
and malloc
are using the same allocator, so there should not be a practical problem here). Does the C++ standard have anything to say on this subject?
(the current glibc standard C++ library does not do realloc, even in vector - because once an object has been allocated the runtime can't call the destructor in place on the old memory block and call placement new on the new block - if the memory block has been moved by realloc
that is. It would have been simpler if the standard library would have had an in-place realloc
that can't move the argument block to a new location)
Actually some memory allocators have an in-place realloc
function; these are of course non-standard.
rallocm
with flag ALLOCM_NO_MOVE
dlrealloc_in_place
If you use jemalloc or dlmalloc for global operator new
and delete
, then you could use these non standard functions for a vector class that attempts in-place realloc
before it does a moving malloc
with copying. Or one could petition the C++ standard committee to add a global non-moving reallocation method to the standard.
or you can do a vector class where memory management is done via malloc
/realloc
/free
, but this implementation may only be instantiated if the element type is plain old data (i.e. if std::is_pod
returns true on the type that the vector is holding).
Upvotes: 2
Views: 680
Reputation: 14395
No, you can't mix free
/realloc
with the built in new
.
Much of the functionality you're seeking may be available using std::vector
. It's guaranteed (AFAIK) that the objects in the vector to be stored contiguously (just like an old style array), you can get the pointer to the storage and you can resize the array in a standard defined way. The only thing that seems to be lacking is the possibility to supply your own storage (ie have a T*
and get a std::vector<T>
with that storage).
What you otherwise might do if you really need to (check the below drawbacks first) is to replace the default implementation of new
and delete
to use malloc
and free
:
void* operator new(size_t n)
{
return malloc(n);
}
void operator delete(void* p)
{
free(p);
}
after doing that, you can use realloc
on a pointer got by new
.
As pointed out by Michael Walz you need to take care if the objects you're allocating requires initialization. It could be even worse if your object can't be moved by just copying the memory (which realloc
does if it can't resize the block in place). This means that it's useless on anything else than dumb structs (and even then you'll end up with C like semantics with uninitialized data anyway - not even zero-initialized).
In addition malloc
, free
and realloc
doesn't play well with C++ stronger typing. This
Upvotes: 6
Reputation: 10613
There is no realloc in c++;
And it's a good thing too! It's a horrible idea. It's not a function - it's a whole family of functions, all rolled into one.
realloc
instead of malloc
? You can!realloc
instead of free
? You can!This bloated interface makes it impossible to use correctly and reliably and even if you suspect an error, the fact that are essentially no incorrect inputs make it hard to debug. Combined with the fact that the result is more often than not used incorrectly, you have, at best, a recipe for memory leaks!
So please, don't think of new ways to use realloc
- especially in C++. And if you see code using it change it to not use it. realloc
needs to die.
Of course you can always allocate a new block with new, copy the old block to the new block, free the old block with delete.
Yes, you can and should do this. It helps explain exactly what's happening, it's less error-prone than calling realloc
and determining if it succeeded or failed, and will always do the right thing when allocating arrays by invoking constructors and destructors at the right time.
The problem is that realloc can often be faster than this - this happens when the memory block is re-sized 'in place' - that is the return value of realloc happens to be the same as the argument pointer value; this also avoids the copying of memory from old block to new block.
With all due respect, the biggest bottleneck of your program is not likely to be memory copying. And starting with C++11 which gave us move semantics, this is more likely to be true than ever.
Of course just because it's unlikely it doesn't mean it's impossible. If you really need to optimize this case (as demonstrated by a thorough performance analysis), you're likely to be better off contemplating ways to avoid the need to reallocate, or spending time tuning your application and adjusting its behavior to cause it allocate more memory from the get-go, reducing the need and/or frequency of reallocations.
Upvotes: 2