1

If I have these 2 lines of code in C++

vector<int> vec = {3,4,5};
vec.push_back(6);

How much memory is allocated in total for the 2 lines and what assumption we need to make? I tried to look these up but can't find the definition for these anywhere.

shjnlee
  • 221
  • 2
  • 6
  • 20
  • `std::cout << (sizeof vec + sizeof(int) * vec.capacity()) << '\n';` should give you a rough idea. [Example](https://godbolt.org/z/jrsavcP6e). Note that different compilers may give different results. – Ted Lyngmo Aug 22 '22 at 06:31
  • Dynamically? at least `sizeof(int)*4`. Run-time allocation can be found via `sizeof(int)*capacity()` for your implementation :P – Swift - Friday Pie Aug 22 '22 at 06:32
  • The C++ standard does not specify how much memory will be allocated in this situation (or in any similar situation). You could consider using `vec.shrink_to_fit();` if you want to minimise memory usage, however even this is only a request to release unused capacity, there are no guarantees. – john Aug 22 '22 at 06:43

2 Answers2

1

Looking at llvm's libcxx library as an example, we could speculate that the capacity would be 6 ints in size.

vector<int> vec = {3,4,5}; allocates 3 ints on initialization __vallocate(3);

template <class _Tp, class _Allocator>
inline _LIBCPP_INLINE_VISIBILITY
vector<_Tp, _Allocator>::vector(initializer_list<value_type> __il)
{
#if _LIBCPP_DEBUG_LEVEL >= 2
    __get_db()->__insert_c(this);
#endif
    if (__il.size() > 0)
    {
        __vallocate(__il.size());
        __construct_at_end(__il.begin(), __il.end(), __il.size());
    }
}

vec.push_back(6); triggers re-allocation with a doubling in capacity 2*__cap

//  Precondition:  __new_size > capacity()
template <class _Tp, class _Allocator>
inline _LIBCPP_INLINE_VISIBILITY
typename vector<_Tp, _Allocator>::size_type
vector<_Tp, _Allocator>::__recommend(size_type __new_size) const
{
    const size_type __ms = max_size();
    if (__new_size > __ms)
        this->__throw_length_error();
    const size_type __cap = capacity();
    if (__cap >= __ms / 2)
        return __ms;
    return _VSTD::max<size_type>(2*__cap, __new_size);
}

https://github.com/llvm-mirror/libcxx/blob/78d6a7767ed57b50122a161b91f59f19c9bd0d19/include/vector

Update (based on ChrisD's comment)

Since the capacity multiplier could be in the range of 1.5 to 2, the size could be 4, 5, or 6 ints.

SargeATM
  • 2,483
  • 14
  • 24
  • 2
    Note the growth rate is implementation dependent. With MSVC it's 1.5x (or at least it used to be), there are some arguments that this is more likely to be the "best" choice . See [here](https://stackoverflow.com/questions/5232198/how-does-the-capacity-of-stdvector-grow-automatically-what-is-the-rate) for more. – ChrisD Aug 22 '22 at 08:16
  • @ChrisD interesting I though x2 was pretty universal. I'm sure glad I said 'speculate' now. :-) – SargeATM Aug 22 '22 at 08:23
  • 1
    It was "speculating using llvm as an example" which was even better qualified! – ChrisD Aug 22 '22 at 08:48
0

I'm not 100% sure, but as I know std::vector initial capacity is implementation-defined. In most compilers it is of size of initializer lists. Size of additional allocations ( if we have not enough capacity to push_back(6) ) is also implementation-defined ( in most compiler current capacity is just doubles ). So, if you want to know exactly how large your vector's capacity is you should use reserve() function. In the example below there are only 1 allocation of vector's capacity( of size 4 * sizeof(int) bytes ) :

std::vector<int> vec;
vec.reserve(4); // reserve memory for 4 ints
push_back(3);
push_back(4);
push_back(5);
push_back(6);
// no additional allocations
ralex
  • 23
  • 4
  • 1
    Even this doesn't work, because `vec.reserve(4)` only guarantees that the capacity will be at least 4, it could be more. AFAIK there is no way to guarantee the exact amount of memory allocated. – john Aug 22 '22 at 07:12