How does adding and removing elements "rescale" the data? How is the size of the vector calculated (I believe it is kept track of)? Any other additional resources to learn about vectors would be appreciated.
Vectors in C++ are sequence containers representing arrays that can change their size during runtime. They use contiguous storage locations for their elements just as efficiently as in arrays, which means that their elements can also be accessed using offsets on regular pointers to its elements.
As mentioned above, std::vector is a templated class that represents dynamic arrays. std::vector typically allocates memory on the heap (unless you override this behavior with your own allocator). The std::vector class abstracts memory management, as it grows and shrinks automatically if elements are added or removed.
std::string offers a very different and much expanded interface compared to std::vector<> . While the latter is just a boring old sequence of elements, the former is actually designed to represent a string and therefore offers an assortment of string-related convenience functions.
A std::vector can never be faster than an array, as it has (a pointer to the first element of) an array as one of its data members. But the difference in run-time speed is slim and absent in any non-trivial program. One reason for this myth to persist, are examples that compare raw arrays with mis-used std::vectors.
In terms of sizing, there are two values of interest for a std::vector
: size
, and capacity
(accessed via .size()
and .capacity()
).
.size()
is the number of elements that are contained in the vector, whereas .capacity()
is the number of elements that can be added to the vector, before memory will be re-allocated.
If you .push_back()
an element, size will increase by one, up until you hit the capacity. Once the capacity is reached, most (all?) implementations, re-allocate memory, doubling the capacity.
You can reserve a capacity using .reserve()
. For example:
std::vector<int> A; A.reserve(1); // A: size:0, capacity:1 {[],x} A.push_back(0); // A: size:1, capacity:1 {[0]} A.push_back(1); // A: size:2, capacity:2 {[0,1]} A.push_back(2); // A: size:3, capacity:4 {[0,1,2],x} A.push_back(3); // A: size:4, capacity:4 {[0,1,2,3]} A.push_back(4); // A: size:5, capacity:8 {[0,1,2,3,4],x,x,x}
Reallocations of memory would occur at lines 4, 5, and 7.
The vector usually has three pointers. If the vector has never been used they are all 0, or NULL.
When an element is inserted, the vector allocates some storage and sets its pointers. It might allocate 1 element, or it might allocate 4 elements. Or 50.
Then it inserts the element and increments the last element pointer.
When you insert more elements than are allocated the vector has to get more memory. It goes out and gets some. If the memory location changes then it has to copy all the elements into the new space and free the old space.
A common choice for resizing is to double the allocation every time it needs more memory.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With