Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reserving capacity for an STD vector<bool> template specialization

I am looking at the space-efficient specialization of std::vector for the type bool i.e. std::vector<bool>. The following MWE creates an object and reserves memory for it:

#include <iostream>
#include <vector>

int main() {
  size_t nn{10};
  std::vector<bool> theVector{};
  theVector.reserve(nn);
}

However, when I compile this MWE with:

$ g++ --version
g++ (Ubuntu 5.4.0-6ubuntu1~16.04.9) 5.4.0 20160609

by doing this:

$ g++ -std=c++14 -g mwe.cpp -o mwe

and then debug using:

$ gdb --version
GNU gdb (Ubuntu 7.11.1-0ubuntu1~16.5) 7.11.1

I get the following output:

Breakpoint 1, main () at mwe.cpp:6
6     size_t nn{10};
(gdb) n
7     std::vector<bool> theVector{};
(gdb) n
8     theVector.reserve(nn);
(gdb) p theVector 
$1 = std::vector<bool> of length 0, capacity 0
(gdb) n
7     std::vector<bool> theVector{};
(gdb) p theVector 
$2 = std::vector<bool> of length 0, capacity 64
(gdb) 

Why do I get a capacity of 64 when I have specified a total capacity of 10?

Previous research led me to read about this template specialization. I learned from cppreference.com that in order to be efficient, this template may: in order to be space efficient, it:

  1. Does not necessarily store its elements as a contiguous array (so &v[0] + n != &v[n])
  2. Exposes class std::vector<bool>::reference as a method of accessing individual bits. In particular, objects of this class are returned by operator[] by value.
  3. Does not use std::allocator_traits::construct to construct bit values.
  4. Does not guarantee that different elements in the same container can be modified concurrently by different threads.

Yet I am failing to see how could these measures yield the behavior that I am encountering.

like image 232
Eduardo Avatar asked Nov 29 '25 19:11

Eduardo


1 Answers

As already pointed out in the comments, the implementation is allowed to over-allocate if it finds that suitable.

The fact that you only see this happening for std::vector<bool> suggests this is due to the way the elements are stored internally.

As you have already learned, std::vector<bool> is commonly specialized to space-efficiently store its elements as bits by packing them into some larger type.

Thus, the actual capacity will always be a multiple of the number of bits that can be stored in the larger type. In this case, said type seems to be 64 bits wide, probably some unsigned 64 bit integer.

like image 199
Baum mit Augen Avatar answered Dec 01 '25 08:12

Baum mit Augen