C++ sizeof Vector is 24?
Asked Answered
E

2

40

I was just messing around and learning about vectors as well as structs, and at one point, I tried outputting the size of a vector in bytes. Here's the code:

#include <iostream>
#include <vector>

struct Foo{
    std::vector<int> a;
};

int main()
{
    using std::cout; using std::endl;   

    Foo* f1 = new Foo;

    f1->a.push_back(5);
    cout << sizeof(f1->a) << endl;
    cout << sizeof(f1->a[0]) << endl;

    delete[] f1;
}

The output is 24 and 4.

Obviously the second line printed 4, because that is the size of an int. But why exactly is the other value 24? Does a vector take up 24 bytes of memory? Thanks!

Ensiform answered 1/12, 2015 at 16:10 Comment(7)
A vector is usually implemented with three pointersWendelina
That's the size of class std::vector<int>. It's implementation-dependant, and it's the sum of the sizes of the members of such a class. Usually a pointer to the underlying C-style array and various members like size, capacity and so on.Contrive
On a side note delete[] f1 is incorrect, it should be delete f1 onlyNerland
@Uchia Itachi Thanks, I wasn't too sure about that. Noted.Ensiform
Since you seem to be learning C++: normally we'd not even use new/delete. We'd write Foo f1; and fi.push_back (dot not arrow).Dasha
@Dasha Yeah, that makes sense. In all honesty this whole block of code was just me familiarizing myself with multiple concepts, but thanks anyway, I'll keep it in mind.Ensiform
Closely related: #32931860Valverde
I
60

While the public interface of std::vector is defined by the standard, there can be different implementations: in other words, what's under the hood of std::vector can change from implementation to implementation.

Even in the same implementation (for example: the STL implementation that comes with a given version of Visual C++), the internals of std::vector can change from release builds and debug builds.

The 24 size you see can be explained as 3 pointers (each pointer is 8 bytes in size on 64-bit architectures; so you have 3 x 8 = 24 bytes). These pointers can be:

  • begin of vector
  • end of vector
  • end of reserved memory for vector (i.e. vector's capacity)
Inure answered 1/12, 2015 at 16:15 Comment(2)
Add to that solutions that try to be smart with 48 bit pointers, SSO, custom allocators, and the size might reasonably be anywhere between 20 and 64 bytes, plus whatever is allocated on the heap.Gianina
Even 16 bytes is realistic: 8 byte pointer to the start, 4 byte element count, 4 byte reservation.Dasha
S
0

Here is the code from libc++'s (ignore the compressed pair, it is an iterator which maintains the capacity of the vector). Here are 3 pointers in the implementation of .

pointer                                    __begin_;
pointer                                    __end_;
__compressed_pair<pointer, allocator_type> __end_cap_;

As pointers are 8 Byte in size on a 64-bit CPU, that is why 8*3 = 24 Byte.

Stonyhearted answered 17/5, 2023 at 19:7 Comment(2)
Compressed pair is used to make sure that, if allocator_type is stateless, the stored allocator doesn't occupy space (it could be implemented e.g. relying e.g. on empty base optimization), but since C++20 you can also use [[no_unique_address]] member for that.Intangible
The reason standard libraries still use their own compressed pairs is that 1) their code should be compatible with previous standards and 2) they abstract away which optimization is used to avoid platform-specific behaviour, because aforementioned optimizations could be sometimes ignored, while library writers can make sure to use a method which will definitely work on target compiler/platform.Intangible

© 2022 - 2024 — McMap. All rights reserved.