2

我正在浏览 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”第二次执行时,这会导致错误的访问崩溃。有任何想法吗?

4

3 回答 3

2

你不应该++boxIt在擦除之后。该分配已经将您的迭代器移动到下一个项目。

从 for 行中删除++boxIt并将其放入elseonly。

于 2013-07-04T23:13:56.467 回答
1

您观察到这种行为的原因是因为向量erase()使现有的迭代器无效。然后你不能增加你的 iterator ++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) 导致错误的内存访问

迭代时删除

迭代向量,边走边删除某些项目

于 2013-07-04T23:26:57.767 回答
0

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

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

您可以尝试使用带有 remove_if 的擦除(后者实际上并不会自行擦除任何内容)

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

于 2013-07-04T23:09:25.753 回答