Consider the following code:
struct Point {
int x;
int& xref = x;
};
int main() {
std::vector<Point> points;
for (int i = 0; i < 2; i++) {
Point p;
p.x = i;
points.push_back(p);
assert (points[0].x == points[0].xref);
}
return 0;
}
The assertion fails on the second iteration. Why?
I'm using the GNU C++ compiler. The problem occurs with all of the standards I've tested:
Every element's xref seems to reference the last added element's x instead of its own, as can be seen here: https://pastebin.com/H4wCszxp
When you push an object into a vector, you make a copy †.
When you copy a reference (that is the member), the new reference will refer to the same object as the one it was copied from. So, if you copy a Point p into a Point copy, then copy::xref will refer to p.x, because that's what p.xref refers to.
So, all Point objects that are within the vector are copies of the Point p automatic variables that were constructed within the scope of the loop. And therefore all of those objects in the vector refer to the int objects that are the member of the automatic variable p. None of them refer to their own x member.
During first iteration this is fine, because points[0].xref refers to an existing p.x, which also has the same value as points[0].x. But at the end of that iteration, the automatic variable p (whose member the points[0].xref refers to) is destroyed. At this point points[0].xref is a dangling reference that no longer refers to a valid object. In the next iteration the reference is used. Using a dangling reference has undefined behaviour.
If you wish to access this object, then use this pointer. If you want to store a reference to an object, then don't expect a copy of that reference to refer to another object. Avoid storing a reference (or a pointer) to an object that has shorter lifetime than the object that holds the reference.
† ... or make a move when you push an rvalue. You don't push an rvalue, and a copy is exactly the same thing as move for Point), so this is an irrelevant detail.
This is happening because when the point is inserted into the vector it get copied, and the reference points to the original value. Eg. this work fine:
int main() {
Point p;
p.x = 100;
assert (p.x == p.xref);
return 0;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With