3

Question :

I tried to print the number of byte and the memory address of elements that are in a vector. The result, I see a memory address and a number of byte. Are the elements of a vector stored separately? And if so, why does my code give me that the vector is only 24 bytes?

What I tried :

#include <iostream>
#include <vector>

int main(){
    std::vector<const char *> colour = {"Microsoft", "Apple", "DELL", "Accer", "Lenovo", "hp"};
    std::cout << "VectorSize : " << sizeof(colour) << "\n" << std::endl;
    for(int i = 0; i < colour.size(); i++){
        std::cout << colour[i] << " is " << sizeof(colour[i]) << " byte at " << &colour[i] << "." << std::endl;
    }
}

Result :

VectorSize : 24

Microsoft is 8 byte at 0x27b5a7c6220.
Apple is 8 byte at 0x27b5a7c6228.
DELL is 8 byte at 0x27b5a7c6230.
Accer is 8 byte at 0x27b5a7c6238.
Lenovo is 8 byte at 0x27b5a7c6240.
Meniev
  • 148
  • 1
  • 13
  • Side note consider using `std::vector` (to avoid having to use raw `const char*` pointers in your code. – Pepijn Kramer Jul 31 '23 at 04:09
  • "Are the elements of a vector stored separately?" Yes. "... and if so, why does my code give me that the vector is only 24 bytes?" Because the elements are stored separately. – user207421 Jul 31 '23 at 05:40
  • Related: [sizeof Vector is 24?](https://stackoverflow.com/q/34024805) – JaMiT Jul 31 '23 at 06:32
  • `const char *` is a pointer, its size doesn't depend on what it points to. And yes, what they point to, the actual strings, are stored elsewhere. – tevemadar Jul 31 '23 at 09:00

3 Answers3

5

How many bytes does a vector use?

Vectors use memory in two places: 1. within the vector object itself, and 2. on the heap, where the vector elements are stored.

Compiler implementers have a lot of freedom in how they allocate this memory. Typically, however, the vector object itself contains the parts that to not change in size. Here is what I found in Microsoft's implementation:

  1. A pointer to the beginning of data on the heap, i.e., to the first data element.

  2. A pointer to the end of data, i.e., one element beyond the final data element. Using this pointer, capacity() is calculated as end - first.

  3. A pointer marking the last element in use, i.e., a pointer to the element following the last data element in use. With this pointer, size() is calculated as last - first.

The array of data elements is stored on the heap, potentially with other implementation specific information (or not).

For a given vector v, assuming that nothing except the array of data elements is stored on the heap, the number of bytes used will be:

sizeof(v) + (v.data() == nullptr ? 0 : v.capacity() * sizeof(*v.data()))

The vector in the original question is a vector of pointers, specifically, pointers to const char. The vector is initialized by an initializer_list with 6 string literals. The string literals are stored in static memory, while the pointers to them are stored on the heap, as vector data. Presumably, the capacity was allocated at 6, but I believe that detail is implementation specific. The size of each element is the size of a data pointer, usually that is the sizeof(std::size_t).

Here is a short program to calculate the total number of bytes used. Hopefully, the original poster will run it on his system, and tell us what he gets.

#include <cstddef>
#include <iostream>
#include <vector>
int main()
{
    std::vector<const char*> v = { "Microsoft", "Apple", "DELL", "Accer", "Lenovo", "hp" };
    std::cout << std::boolalpha
        << "sizeof(v)           : " << sizeof(v)
        << "\nv.size()            : " << v.size()
        << "\nv.capactity()       : " << v.capacity()
        << "\nv.data() == nullptr : " << (v.data() == nullptr)
        << "\nv.data()            : " << v.data()
        << "\nsizeof(*v.data())   : " << sizeof(*v.data())
        << "\nsizeof(std::size_t) : " << sizeof(std::size_t)
        << "\nTotal bytes used    : " << sizeof(v) + (v.data() == nullptr ? 0 : v.capacity() * sizeof(*v.data()))
        << "\n\n";
    return 0;
}

I ran on MSVC, targeting x64, so my pointers were 8 bytes each. Evidently, there is a fourth item stored in the vector object, because the sizeof(v) came out at 32, rather than 24.

sizeof(v)           : 32
v.size()            : 6
v.capactity()       : 6
v.data() == nullptr : false
v.data()            : 000002952A005030
sizeof(*v.data())   : 8
sizeof(std::size_t) : 8
Total bytes used    : 80

In reading through Microsoft's source code for header <vector>, I was able to locate the three pointers mentioned above. They are stored in an object named _Mypair as _Mypair._Myval2. I could not, however, find the definition for _Mypair._Myval1, which, presumably, is the fourth item.

When I recompiled, targeting x86, the size was cut in half. That makes sense, because std::size_t, the size used for pointers, had its size cut down to 4 bytes.

sizeof(v)           : 16
v.size()            : 6
v.capactity()       : 6
v.data() == nullptr : false
v.data()            : 00AEC640
sizeof(*v.data())   : 4
sizeof(std::size_t) : 4
Total bytes used    : 40
tbxfreeware
  • 547
  • 1
  • 9
4

The data in a vector is allocated dynamically and stored in another memory location, it is not part of the vector, and the vector only has a pointer to this memory. The allocated memory is contiguous, so all allocated bytes are next to each other in memory.

In your case it the size of the class std::vector is 24 bytes, the size of the extra allocated memory somewhere else in memory is 40 bytes. So in total 64 bytes will be allocated in your computers memory.

Pepijn Kramer
  • 9,356
  • 2
  • 8
  • 19
3

sizeof(...) measures size of the object. It is unrelated to the number of elements that std::vector has. Write colour.size() to compute that. With vector sizeof(std::vector) == 24 is because it contains, pointer to data, current number of elements, and capacity of the allocated data, each taking 8 bytes on your architecture. Different implementations might implement it differently.

Yes, as you can see the pointer's location each time increases by 8, as vector's data is stored contiguously.

templatetypedef
  • 362,284
  • 104
  • 897
  • 1,065
ALX23z
  • 4,456
  • 1
  • 11
  • 18