stdvector插入和擦除问题

时间:2011-07-27 20:04:02

标签: c++ stdvector openframeworks

我需要控制应用程序中触摸点的数量,为此我使用的是矢量容器,我的基本设置是这样的:

//--------------------------------------------------------------
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;
    }
}

但是当我向上移动手指时,应用程序会冻结,所以touchUp()中出现了大多数错误,有什么想法吗?

2 个答案:

答案 0 :(得分:4)

很多事情:首先,您不能修改(擦除/插入)容器并期望迭代器保持有效!

我们来看看。我也想修改touchMove

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

接下来,重要的一个:

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

基本上touch.id 只是向量中的索引,因此我们可以直接使用它。要从中间删除元素,我们只需在相应的迭代器上调用erase。由于vector具有随机访问迭代器,我们可以在常量时间内说begin() + touch.id

更新:实际上我认为您的代码已损坏:从向量中删除元素后,其他元素向上移动,因此您将失去touch.id与容器之间的关联元件!你猜对了,需要的是一个关联容器:

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);
  }
};

答案 1 :(得分:0)

如果您已完成iter=touchPoints.erase(iter),则不应该++iter;你已经转到了下一个项目。