问题描述:

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)

edit:

Actually some memory allocators have an in-place realloc function; these are of course non-standard.

  • jemalloc has an API called rallocm with flag ALLOCM_NO_MOVE
  • dlmalloc (Doug Lea malloc) has an API called 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.

edit:

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).

网友答案:

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

网友答案:

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.

  • Want to use realloc instead of malloc? You can!
  • Want to use realloc instead of free? You can!
  • Want to grow a memory block? Yes, yes you can!
  • Want to shrink it? Why yes, you can do this too.
  • Want to do nothing at all with it? Of course you can. Did you even need to ask?

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. reallocneeds 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.

相关阅读:
Top