【问题标题】:Why my pointers get invalidated, if I don't use vector.reserve()?如果我不使用 vector.reserve(),为什么我的指针会失效?
【发布时间】:2017-03-06 18:00:11
【问题描述】:

我有一小段代码,其中包含一个用于二维顶点的类 (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->x(), event->y()));) 则 m_lines 向量中的线 dissaperas 和值将更改为非常随机的大数字。我读了一些关于指针失效的东西。如果您将新值推送到向量,那么某些值最终会被扩展。我还使用 vector::reserve 解决了我的问题,但既然我确定我做的不对,谁能解释我应该如何使用 vector::reserve 以及为什么我需要这样做?

【问题讨论】:

  • 1) 修正缩进。 2) 创建minimal reproducible example。 3)尝试使用调试器,单步执行您的代码,同时检查每一步的变量值。按此顺序。

标签: c++ pointers memory vector


【解决方案1】:

我没有仔细查看您的代码,但似乎是向量的重新分配给您带来了麻烦。

向量总是跟踪两个大小:它的容量和它包含的对象的数量。如果您执行 push_back,并且它的容量已经达到最大值,它会将自己复制到内存中具有更多空间和更大容量的另一个位置。您的指针可能仍指向原始位置。

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

编辑:您遍历一个可以执行插入操作的数组。那不应该。

【讨论】:

    【解决方案2】:

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

    调用reserve 告诉向量预先分配一块内存,以便任何后续 push_back 可以保证不需要重新分配(如果你留在保留范围内(实际上capacity)),因此不会使指向元素的迭代器/指针无效。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-01-29
      • 1970-01-01
      • 2022-11-22
      • 1970-01-01
      • 1970-01-01
      • 2011-08-22
      • 2018-03-23
      相关资源
      最近更新 更多