A different question inspired the following thought:
Does std::vector<T> need to move all elements while increasing its capacity?
As I understand it, the standard behavior is that the base allocator will request the entire fragment of a new size, then move all the old elements, then destroy the old elements and then free up the old memory.
This behavior is the only possible correct solution, given the standard distributor interface. But I was wondering if it would be advisable to make corrections to the allocator to offer the reallocate(std::size_t) function, which would return pair<pointer, bool> and could map to the base realloc() ? The advantage of this would be that if the OS could actually just expand the allocated memory, then no movement should occur at all. A boolean value indicates whether memory has been moved.
( std::realloc() may not be the best choice, because we don’t need to copy the data if we can’t extend it. So we really would like to get something like extend_or_malloc_new() . Edit: Maybe is_pod - Specialized specialization would allow us to use the actual realloc , including a battered copy of it. Just not in general.)
Seems like a missed opportunity. In the worst case, you can always implement reallocate(size_t n) as return make_pair(allocate(n), true); therefore there would be no penalty.
Is there any problem that makes this function unacceptable or undesirable for C ++?
Perhaps the only container that can take advantage of this is std::vector , but again, that is a pretty useful container.
Update: A small example to clarify. Current resize() :
pointer p = alloc.allocate(new_size); for (size_t i = 0; i != old_size; ++i) { alloc.construct(p + i, T(std::move(buf[i]))) alloc.destroy(buf[i]); } for (size_t i = old_size; i < new_size; ++i) { alloc.construct(p + i, T()); } alloc.deallocate(buf); buf = p;
New implementation:
pair<pointer, bool> pp = alloc.reallocate(buf, new_size); if (pp.second) { } else { }
c ++ vector realloc allocator
Kerrek SB Nov 03 '11 at 23:30 2011-11-03 23:30
source share