2017-03-06 76 views
-2

我有一小段代码,它包含一个用于二维顶点的类矢量(Vector2)和一个向Vector2类型对象提供参数的模板类DynamicLine矢量。为什么我的指针失效,如果我不使用vector.reserve()?

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-> x(),event-> y()));),则线条dissaperas和m_lines矢量中的值将更改为非常随机的大数字。我读了一些关于指针失效的信息。如果你将新的值推向矢量,那么最终会有一些扩展。我也使用vector :: reserve修复了我的问题,但由于我确定我没有这样做,任何人都可以请解释我应该如何使用vector :: reserve以及为什么我需要这样做?

+2

1)修复你的缩进。 2)创建[mcve]。 3)尝试使用调试器来遍历代码,同时在每个步骤检查变量的值。以该顺序。 –

回答

1

我没有仔细看过你的代码,但它好像是重新分配给你造成麻烦的向量。

矢量始终跟踪两种尺寸:其容量和其包含的对象数量。如果您执行push_back操作,且其容量已达到最大值,则会将其自身复制到内存中具有更多空间和更大容量的其他位置。你的指针可能仍然指向原始位置。

使用向量时,最好保持索引而不是指针。

编辑:你迭代你可以执行插入操作的数组。这不应该。

1

这很简单。当你push_backvector没有足够的capacity它需要分配更多的内存并将你的元素复制(或移动)到新的位置。这会使任何指向旧元素的迭代器/指针无效(它们现在只是指向旧的释放内存块),这意味着它们基本上指向垃圾 - 所以你必须在push_back之后获得新的迭代器。

调用reserve告诉矢量分配的内存块的前期,使得任何随后push_back可以保证不需要重新分配(如果留下的预约(实际上capacity)内),并因此将不无效迭代器/指向元素的指针。

相关问题