我有一小段代码,它包含一个用于二维顶点的类(Vector2)向量和一个模板类DynamicLine的向量,它将Vector2类型对象作为参数。
std::vector<Vector2> m_coords;
std::vector<DynamicLine<Vector2>> m_lines;
Vector2 *lineVec = NULL;
bool draw = true;
case DrawingWidgetState::ADD_VERTEX_SELECTED:{
for(auto it = m_coords.begin(); it != m_coords.end(); it++)
if(it->distanceFrom(Vector2(event->x(), event->y())) < 20 && !m_coords.empty()){
draw = false;
break;
}
if(draw){
if(event->x() < m_mainWindow->width() - 10 && event->x() >= 10
&& event->y() < m_mainWindow->height() && event->y() >= 10) {
m_coords.push_back(Vector2(event->x(), event->y()));
update();
}
}
break;
}
case DrawingWidgetState::ADD_LINE_SELECTED:{
for(auto it = m_coords.begin(); it != m_coords.end(); it++)
if(it->distanceFrom(Vector2(event->x(), event->y())) < 10){
if(!i){
lineVec = &(*it);
i++;
}
else{
m_lines.push_back(DynamicLine<Vector2>(lineVec, &(*it)));
i = 0;
}
update();
break;
}
break;
}
接下来是问题。例如,如果我在它们之间添加两个顶点和一条线,那么一切正常。但是,如果我现在添加另一个顶点(m_coords.push_back(Vector2(event-&gt; x(),event-&gt; y()));)那么m_lines向量中的行dissaperas和值将更改为非常随机的大数字。我读了一些关于指针失效的内容。如果将新值推送到vector,那么最终会扩展一些值。我还使用vector :: reserve修复了我的问题,但是因为我确定我没有做到这一点,任何人都可以解释一下我应该如何使用vector :: reserve以及为什么我需要这样做?
答案 0 :(得分:1)
我没有密切关注你的代码,但似乎是导致你麻烦的向量重新分配。
矢量始终跟踪两种尺寸:容量和它包含的对象数量。如果你做了push_back,并且它的容量已经达到最大值,它会将自身复制到内存中的另一个位置,空间更大,容量更大。你的指针可能仍然指向原始位置。
使用向量时,最好保留索引而不是指针。
编辑:迭代可以执行插入操作的数组。那不应该。
答案 1 :(得分:1)
这很简单。当push_back
和vector
没有足够capacity
时,它需要分配更多内存并将元素复制(或移动)到新位置。这会使指向旧元素的任何迭代器/指针无效(它们现在只是指向旧的释放内存块),这意味着它们基本上指向垃圾 - 所以你必须在push_back
之后获得新的迭代器。
调用reserve
告诉向量预先分配一块内存,以便保证任何后续 push_back
不需要重新分配(如果你留在保留(实际上是capacity
))因此不会使元素的迭代器/指针无效。