Reputation: 3383
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 MultiDimPoint
s 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
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
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 int
s. 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