Show Lecture.ContainerSizes as a slide show.
CS253 Container Sizes
Container sizes
A vector, and some other containers that use
contiguous allocation,
have several kinds of sizes defined:
.size()
: how many elements the vector currently contains
.capacity()
: how many elements are allocated, or,
how many elements it could contain before reallocation
.max_size()
: biggest possible .size()
on this computer
.size()
is how much the box is holding now,
.capacity()
is the volume of a box,
and .max_size()
is the maximum size a box could be before
it undergoes gravitational collapse.
Example
vector<int> v;
cout << "size=" << v.size() << '\n'
<< "capacity=" << v.capacity() << '\n'
<< "max_size=" << v.max_size() << '\n';
size=0
capacity=0
max_size=2305843009213693951
vector<char> v(42);
cout << "size=" << v.size() << '\n'
<< "capacity=" << v.capacity() << '\n'
<< "max_size=" << v.max_size() << '\n'
<< "2⁶³=" << (1ULL<<63) << '\n';
size=42
capacity=42
max_size=9223372036854775807
2⁶³=9223372036854775808
Dynamic Resizing
vector<int> v;
for (int i=0; i<18; i++) {
v.push_back(42);
cout << "size=" << v.size() << ' '
<< "capacity=" << v.capacity() << '\n';
}
size=1 capacity=1
size=2 capacity=2
size=3 capacity=4
size=4 capacity=4
size=5 capacity=8
size=6 capacity=8
size=7 capacity=8
size=8 capacity=8
size=9 capacity=16
size=10 capacity=16
size=11 capacity=16
size=12 capacity=16
size=13 capacity=16
size=14 capacity=16
size=15 capacity=16
size=16 capacity=16
size=17 capacity=32
size=18 capacity=32
Change sizes
.reserve(
n)
: change the allocated size of this
container. However, you can’t allocate less than your current
.size()
. This changes .capacity()
. This does not
change .size()
.
.resize(
n)
: change the size of this container.
If it had more than n elements before, we lose some. If it had
fewer than n elements, add default-constructed elements.
This changes .size()
. It may change .capacity()
.
.shrink_to_fit()
:
Get rid of any additional reserved memory, as if via
.reserve(.size())
.
Example with .reserve()
vector<int> v;
v.reserve(7);
for (int i=0; i<18; i++) {
v.push_back(42);
cout << "size=" << v.size() << ' '
<< "capacity=" << v.capacity() << '\n';
}
size=1 capacity=7
size=2 capacity=7
size=3 capacity=7
size=4 capacity=7
size=5 capacity=7
size=6 capacity=7
size=7 capacity=7
size=8 capacity=14
size=9 capacity=14
size=10 capacity=14
size=11 capacity=14
size=12 capacity=14
size=13 capacity=14
size=14 capacity=14
size=15 capacity=28
size=16 capacity=28
size=17 capacity=28
size=18 capacity=28
Example with .resize()
vector<int> v;
v.resize(7);
for (int i=0; i<18; i++) {
v.push_back(42);
cout << "size=" << v.size() << ' '
<< "capacity=" << v.capacity() << '\n';
}
size=8 capacity=14
size=9 capacity=14
size=10 capacity=14
size=11 capacity=14
size=12 capacity=14
size=13 capacity=14
size=14 capacity=14
size=15 capacity=28
size=16 capacity=28
size=17 capacity=28
size=18 capacity=28
size=19 capacity=28
size=20 capacity=28
size=21 capacity=28
size=22 capacity=28
size=23 capacity=28
size=24 capacity=28
size=25 capacity=28
Strings, too
string s;
for (int i=0; i<18; i++) {
s += 'x';
cout << "size=" << s.size() << ' '
<< "capacity=" << s.capacity() << '\n';
}
size=1 capacity=15
size=2 capacity=15
size=3 capacity=15
size=4 capacity=15
size=5 capacity=15
size=6 capacity=15
size=7 capacity=15
size=8 capacity=15
size=9 capacity=15
size=10 capacity=15
size=11 capacity=15
size=12 capacity=15
size=13 capacity=15
size=14 capacity=15
size=15 capacity=15
size=16 capacity=30
size=17 capacity=30
size=18 capacity=30
How about a set?
set<int> s;
for (int i=0; i<17; i++) {
s.insert(i);
cout << "size=" << s.size() << ' '
<< "capacity=" << s.capacity() << '\n';
}
c.cc:5: error: ‘class std::set<int>’ has no member named ‘capacity’
- The only reason that vector and string have this
.capacity()
business is that it’s more efficient to have the data be all together
(i.e., contiguous).
- This doesn’t apply to a set or map, which generally use binary
trees, or list, which is a doubly-linked list.
There is a free function, size(), which returns the size of
a container (by calling .size()
) or the size of an array
(because the size of an array is known at compile-time).
vector<int> v = {11,22,33};
double d[] = {1.2, 3.4, 5.6, 7.8};
cout << v.size() << ' ' << size(v) << '\n'
<< size(d) << '\n';
3 3
4
It’s used for template code (patience) that has to work for a container
or an old-style C array. It’s also darn handy for getting the size of a
C array while keeping DRY.
short *p, a[42];
string s;
cout << sizeof(p) << '\n'
<< sizeof(a) << '\n'
<< sizeof(a[0]) << '\n'
<< sizeof(a)/sizeof(a[0]) << '\n'
<< size(a) << '\n'
<< sizeof(s) << '\n'
<< s.size() << '\n';
8
84
2
42
42
32
0
There are three functions with similar names:
- sizeof()
-
a compile-time function that returns the size of an object in bytes
-
.size()
-
a container method, returns number of elements
- size()
-
a free function, identical to
.size()
for containers,
returns the number of elements for a C array.