use*_*008 2 c++ reference stdvector
请考虑以下代码:
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;
}
Run Code Online (Sandbox Code Playgroud)
断言在第二次迭代时失败.为什么?
我正在使用GNU C++编译器.我测试的所有标准都会出现问题:
每个元素xref似乎都引用了最后添加的元素x而不是它自己的元素,如下所示:https://pastebin.com/H4wCszxp
将对象推入向量时,可以复制†.
复制引用(即成员)时,新引用将引用与复制引用相同的对象.所以,如果你Point p把a 复制成a Point copy,那么copy::xref就会引用p.x,因为p.xref那是指的.
因此,Point向量中的所有对象都是在Point p循环范围内构造的自动变量的副本.因此,向量中的所有这些对象都引用int作为自动变量成员的对象p.他们都没有提到他们自己的x成员.
在第一次迭代期间,这很好,因为它points[0].xref指的是一个现有的p.x,它也具有相同的值points[0].x.但是在该迭代结束时,自动变量p(其成员points[0].xref引用)被销毁.此时points[0].xref是一个不再引用有效对象的悬空引用.在下一次迭代中,使用引用.使用悬空引用具有未定义的行为.
如果要访问此对象,请使用this指针.如果要存储对象的引用,则不要指望该引用的副本引用另一个对象.避免将引用(或指针)存储到比保存引用的对象具有更短生命周期的对象.
†...或推动右值时移动.你没有推rvalue,副本与move for完全相同Point,所以这是一个无关紧要的细节.