Direct comparison
| std::vector | C memory functions
------------------------+------------------+------------------------
default capacity | undefined | undefined
default grow | towards capacity | undefined
deterministic capacity | available | no
deterministic grow | available | no
deterministic mem.-move | available | no
non-POD types | yes | f***ing no (*)
no-throw | no | yes
deterministic mem.-move
follows from deterministic capacity/grow
. It is when realloc
and std::vector
have to move their stored elements to a new memory location.
I think the (available) determinism with regards to memory moving is doubly important when you consider moving (smart) references of any kind.
NOTE: In this respect, I use the term "deterministic" with respect to my source codes lifetime, i.e. its lifetime across different versions of different libraries with different compile flags, etc..
Source
It does fragment memory as much as realloc
does:
Class template vector overview [vector.overview]
The elements of a vector are stored contiguously, meaning that if
v
is avector<T, Allocator>
whereT
is some type other thanbool
, then it obeys the identity&v[n] == &v[0] + n
for all0 <= n < v.size()
In other words, the memory used is in one piece.
The one big difference is that realloc
can actually increase allocated memory portions without having ordered it to do so, however, it is not required to do so (man 3 realloc
):
man 3 realloc
The realloc() function changes the size of the memory block pointed to by ptr to size bytes. The contents will be unchanged in the range from the start of the region up to the minimum of the old and new sizes. If the new size is larger than the old size, the added memory will not be initialized. If ptr is NULL, then the call is equivalent to malloc(size), for all values of size; if size is equal to zero, and ptr is not NULL, then the call is equivalent to free(ptr). Unless ptr is NULL, it must have been returned by an earlier call to malloc(), cal‐ loc() or realloc(). If the area pointed to was moved, a free(ptr) is done.
So it can increase the size, but is not required to.
A std::vector
carries not only a size
, but also a capacity
. If you know beforehand you will need a big vector
, yet you cannot initialize everything right now, you are entitled to increase the capacity of your vector like so:
std::vector<T> vec(32);
vec.reserve(1024);
// vec has size 32, but reserved a memory region of 1024 elements
So, unlike realloc
, the moment when reallocations occur can be deterministic with std::vector
.
To answer your question: Because there is std::vector
, realloc
is not needed. And, realloc
is not allowed for non-POD types; attempts to use malloc
, free
and realloc
directly on non-PODs yields undefined behaviour.