Search code examples
c++memoryallocator

Is there a way to resize a buffer in C++


I'm a noob to memory management so please forgive me. Say I have the following code:

std::allocator<T> alloc;

T* buffer = alloc.allocate(42); 

Is there a good way to "add space" to this buffer, instead of creating a new buffer, allocating more space, copying the old buffer to the new buffer, and then replacing the old buffer?


Solution

  • Short answer: No.

    In general you can't use realloc. The problem is that resizing the buffer may or may not mean allocating a new, larger buffer somewhere else and then it depends on T what you have to do. T may be trivially copyable, in which case realloc would work. But it's unlikely for realloc to actually just grow the buffer. That only happens when you accidentally have reusable memory after the old buffer. Basically never happens.

    If T is not trivially copyable then calling realloc is UB when it needs to allocate a new buffer somewhere else. T might have a copy constructor that needs to be called on every object when it is copied. realloc won't do that. You have to allocate a new buffer and copy all the objects from the old buffer to the new buffer. No big loss since the chance that realloc will actually be able to just grow the buffer is miniscule.

    Better if T has a move constructor because that's faster than copying. But then you have to consider what happens when the constructor throws an exception. Maybe somewhere in the middle when you have moved half your objects. So you have to move everything back to the old buffer before throwing the exception again. What if that causes another exception?

    Basically you don't want to move unless the move constructor is noexcept. Copying is the safer fallback.

    All of those things and probably a bunch more have been considered in std::vector, which is why you should just use that.