【问题标题】:c++ deletion from vector of pointersc++ 从指针向量中删除
【发布时间】:2013-07-02 23:21:17
【问题描述】:

我正在浏览 Cinder 的 Box2D 模板中的代码,并且想要修改代码,以便我可以从屏幕上删除框并添加它们。我是 C++ 新手,但根据我从其他 SO 帖子中学到的知识,我正在尝试使用这种情况从向量中删除框:

for( vector<b2Body*>::iterator boxIt = mBoxes.begin(); boxIt != mBoxes.end(); ++boxIt ) {
    if( (*boxIt)->GetPosition().x > scaledX){
        boxIt = mBoxes.erase(boxIt);
    }
    else {

        Vec2f pos( (*boxIt)->GetPosition().x, (*boxIt)->GetPosition().y );
        float t = toDegrees( (*boxIt)->GetAngle() );

        glPushMatrix();
        gl::translate( pos );
        gl::rotate( t );

        Rectf rect( -BOX_SIZE, -BOX_SIZE, BOX_SIZE, BOX_SIZE );
        gl::drawSolidRect( rect );

        glPopMatrix();
    }

}

但是当“(*boxIt)->GetPosition().x”第二次执行时,这会导致错误的访问崩溃。有什么想法吗?

【问题讨论】:

  • 第二次是什么意思?
  • 我添加了一些 cout 行来查看程序崩溃的位置;它成功地运行了一次 if 案例(这向我表明对擦除的调用正在工作),但是当再次执行 if 守卫时它崩溃了。我假设 *boxIt 不再有效,但我不确定为什么。

标签: c++ pointers vector iterator


【解决方案1】:

你不应该在删除后++boxIt。该分配已将您的迭代器移至下一项。

从 for 行中删除 ++boxIt 并将其仅放在 else 中。

【讨论】:

    【解决方案2】:

    您观察到这种行为的原因是因为向量的erase() 使现有迭代器无效。然后你不能增加你的迭代器++boxIt。然而erase() 返回一个新的迭代器,指向被移除的元素之后的元素。你可以使用这个返回的迭代器继续迭代你的向量。

    所以,你可以这样编码:

    vector<b2Body*>::iterator boxIt = mBoxes.begin();
    while (boxIt != mBoxes.end();) {
        if( (*boxIt)->GetPosition().x > scaledX){
            boxIt = mBoxes.erase(boxIt);
        }
        else {
    
            Vec2f pos( (*boxIt)->GetPosition().x, (*boxIt)->GetPosition().y );
            float t = toDegrees( (*boxIt)->GetAngle() );
    
            glPushMatrix();
            gl::translate( pos );
            gl::rotate( t );
    
            Rectf rect( -BOX_SIZE, -BOX_SIZE, BOX_SIZE, BOX_SIZE );
            gl::drawSolidRect( rect );
    
            glPopMatrix();
            boxit++;
        }
    }
    

    看这里:

    Vector.erase(Iterator) causes bad memory access

    deleting while iterating

    iterate vector, remove certain items as I go

    【讨论】:

      【解决方案3】:

      您的问题是您正在擦除一个迭代器,然后继续使用它进行迭代。

      对于矢量every iterator and reference after the point of erase is invalidated.(此处对其他情况进行很好的概述:http://kera.name/articles/2011/06/iterator-invalidation-rules/

      您可以尝试将erase 与remove_if 一起使用(后者实际上并不会自行擦除任何内容)

      http://en.wikipedia.org/wiki/Erase-remove_idiom

      【讨论】:

      • 我的印象是“boxIt = mBoxes.erase(boxIt);”这一行将保持迭代器的有效性(因为 boxIt 现在只包含仍然存在的元素)。这是不正确的吗?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-06-24
      • 1970-01-01
      • 1970-01-01
      • 2014-04-28
      • 1970-01-01
      • 1970-01-01
      • 2013-09-24
      相关资源
      最近更新 更多