marcman
marcman

Reputation: 3383

Memory layout of C++ vector of structs

Let's say I have a struct

struct Point
{
    int x;
    int y;
    int z;
};
Point p = {1,2,3};

I understand that in memory it is organized contiguously as

p = | 1 | 2 | 3 |

If I have a std::vector of Point structs, does the data() function return the array contiguously too? Or is there extra "stuff" thrown in as well? For example

Point p1 = {1,2,3};
Point p2 = {4,5,6};
Point p3 = {7,8,9};
std::vector<Point> points;
points.push_back(p1);
points.push_back(p2);
points.push_back(p3);

Would calling points.data() return the pointer to an array that looks like:

| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8| 9 |
 ^ptr

Furthermore, if the struct were more slightly more complex, containing a vector, let's say

MultiDimPoint
{
    std::vector<int> values;
}

would a vector of these MultiDimPoints also be contiguous? That is, would

MultiDimPoint mdp1;
mdp1.values = std::vector<int>(0,1,2,3);

MultiDimPoint mdp2;
mdp2.values = std::vector<int>(4,5,6,7,8,9);

std::vector<MultiDimPoint> mdp_vec;
mdp_vec.pushback(mdp1);
mdp_vec.pushback(mdp2);

give

| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8| 9 |
 ^ptr

when mdp_vec.data() was called?

Upvotes: 2

Views: 2237

Answers (2)

Khouri Giordano
Khouri Giordano

Reputation: 796

It is required that std::vector pack the elements in a linear array. However, sizeof(Point) may not be three times the size of an int. It might be rounded up to a size convenient for your compiler. There are usually pragmas to control structure packing.

Each vector allocates its own memory, so in the case of MultiDimPoint, they most likely would not be contiguous. If they were, it would be a coincidence. Also, the C runtime heap management may put extra data before and/or after the buffer you requested.

Upvotes: 1

Sam Varshavchik
Sam Varshavchik

Reputation: 118330

The C++ standard leaves it up to each C++ implementation to define and use any padding for structures, that the particular implementation needs.

It is possible that your C++ compiler will add some padding to this struct, for hardware-driven alignment purposes, which would result in some "gaps" between instances of this struct in a vector.

Having said that, you're unlikely to encounter this kind of padding on modern C++ implementations for classes that contain just plain ints. You can determine whether or not this is the case for your C++ implementation by observing what sizeof of this struct is, versus a sizeof of a single int.

But if your goal is to write portable code that should work properly on any C++ implementation, you should not make any kind of assumptions.

Now, when you have a vector as a member of another class, and a vector of those classes, each vector in each class member is completely independent of each other, and you have no guarantees that vectors in consecutive class members will end up being in one consecutive memory block. In fact, you're pretty much guaranteed that they won't be.

Upvotes: 3

Related Questions