开发者

stdvector inserting and erasing problem

I need to control the amount to touch points in my application, for this I am using a vector container and my basic setup is this:

//--------------------------------------------------------------
void testApp::touchDown(ofTouchEventArgs &touch){
    isTouching = true;

    touchPoints.push_back( ofVec2f( touch.x, touch.y ) );
}

//--------------------------------------------------------------
void testApp::touchMoved(ofTouchEventArgs &touch){
    for ( int i = 0; i < touchPoints.size(); i++ ) {
        if ( touch.id == i ) {
            touchPoints[i] = ofVec2f( touch.x, touch.y );
        }
    }
}

//--------------------------------------------------------------
void testApp::touchUp(ofTouchEventArgs &touch){
    isTouching = false;

    int i = 0;
    for ( vector<ofVec2f>::iterator iter = touchPoints.begin(); iter != touchPoints.end(); ) {
        //int i = std::distance( touchPoints.begin(), iter );
        cout << "i: " << i << endl;
        if ( touch.id == i ) {
            iter = touchPoints.erase( iter );
        }
        i++;
        ++iter;
    }
}

But when I move up a finger the app freezes, so there most be something wrong in th开发者_运维技巧e touchUp(), any ideas?


Many things: First off, you cannot modify (erase/insert) a container and expect iterators to remain valid!

Let's see. I want to modify touchMove as well:

void testApp::touchMoved(const ofTouchEventArgs & touch)
{
  if (touch.id < touchPoints.size())
    touchPoints[touch.id] = ofVec2f(touch.x, touch.y);
}

Next, the big one:

void testApp::touchUp(const ofTouchEventArgs & touch)
{
  if (touch.id < touchPoints.size())
    touchPoints.erase(touchPoints.begin() + touch.id);
}

Basically touch.id is just the index in the vector, so we can use that directly. To erase an element from the middle, we just call erase on the corresponding iterator. Since vector has random access iterators, we can say begin() + touch.id in constant time.

Update: Actually I think your code is broken: After you erase an element from the vector, the other elements move up, so you will lose the association between touch.id and the container element! What's needed is, you guessed it, an associative container:

struct testApp
{
  std::map<int, ofVec2f> touchPoints;
  bool isTouching;

  void touchDown(const ofTouchEventArgs & touch)
  {
    isTouching = true;
    touchPoints[touch.id] = ofVec2f(touch.x, touch.y);
  }

  void touchMoved(const ofTouchEventArgs & touch)
  {
    touchPoints[touch.id] = ofVec2f(touch.x, touch.y);
  }

  void touchUp(const ofTouchEventArgs & touch)
  {
    isTouching = false;
    touchPoints.erase(touch.id);
  }
};


If you've done iter=touchPoints.erase(iter) you shouldn't then do ++iter; you've already moved on to the next item.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜