超出范围的向量擦除迭代器
Vector erase iterator outside of range
link 到项目
我正在创建一个将绘制电路组件的小型过剩应用程序。
我有一个名为 "Component" 的 class,看起来像这样:
// nextIndex is the index of the next component to be created
int Component::nextIndex = 0;
Component::Component( void ){
setType( RESISTOR );
setValue( 0.0 );
setX( 0.0 );
setY( 0.0 );
setSize( 2.0 );
setIndex( nextIndex );
}
eType Component::getType( void ){return cType}
double Component::getValue( void ){return cValue;}
double Component::getX( void ){return cX;}
double Component::getY( void ){return cY;}
double Component::getSize( void ){return cSize;}
void Component::setType( eType type ){cType = type;}
void Component::setValue( double value ){cValue = value;}
void Component::setX( double x){cX = x;}
void Component::setY( double y ){cY = y;}
void Component::setSize( double size ){cSize = size;}
int Component::getIndex( void ){return index;}
void Component::setIndex( int n ){index = n;}
注意:每次创建 class 的新实例时,我都会递增 nextIndex。
这是我的另一个 class,它有一个组件向量并处理组件的添加和删除:
class OGWindow{
private:
bool LINK, DELETE;
int linkNo;
...
Component currentSquare;
Component *currentSquarePtr, *linkSquPtr1, *linkSquPtr2;
double squareXStart, squareYStart, squareXEnd, squareYEnd;
std::vector< Component > compVector;
public:
...
void myMouseClick(int button, int state, int x, int y);
...
void deleteSquare( Component *squPtr );
};
我正在为 window 创建组件,就像这样:
整数 NEXT_INT = 0;
if (x >= createButtonX && x <= createButtonX + createButtonWidth) {
cout << "Clicked Create button" << endl;
Component *compPtr = new Component;
compPtr->setX(0.0);
compPtr->setY(0.0);
compPtr->setIndex(NEXT_INT);
NEXT_INT++;
compVector.push_back(*compPtr);
//------------SET THE CURRENT SQUARE TO THE NEWLY CREATED COMPONENT-----
vector<Component>::iterator constIterator;
for (constIterator = compVector.begin(); constIterator != compVector.end(); ++constIterator){
currentSquarePtr = &(*constIterator);
}
cout << "Vector size: " << compVector.size() << endl;
glutPostRedisplay();
}
但是当我删除时,它会删除一些元素,最后一个元素我得到 "vector out of range" 错误:
void OGWindow::deleteSquare( Component *squPtr ) {
compVector.erase(compVector.begin() + (squPtr->getIndex()));
cout << "Vector size: " << compVector.size() << endl;
glutPostRedisplay();
}
请分享发生这种情况的任何想法。
您对 Component
对象的索引存在一些问题。
首先,向量的索引类似于数组,即基于零。因此,如果您有一个仅包含一个元素的向量,则索引(以及距 begin()
迭代器的偏移量)为 zero。其他任何内容均超出范围。
您似乎有一个用于下一个索引的 static
成员变量,并且您将该变量初始化为 1
,这在向量中总是错误的第一个索引。然后在 Component
构造函数中你增加这个静态 nextIndex
变量导致你创建的第二个对象有索引 2
但在向量中它将有索引 1
(如果你有向量中的两个对象)。
从向量中删除对象时会出现另一个问题。除了使用错误索引的(现在很明显)问题之外,您不会对向量中的索引重新编号。因此,如果向量中有两个元素具有(错误的)索引 1
和 2
,并删除第一个元素,那么新的第一个元素将具有更错误的索引 2
.
我解决这个问题的建议是完全不使用索引,而是实现一个比较运算符来实现相等性。然后你可以使用例如std::find
找到向量中的对象,然后用 std::find
.
返回的正确迭代器调用 erase
那么 deleteSquare
看起来像
void OGWindow::deleteSquare( Component const &squRef ) {
auto iterator = std::find( std::begin(compVector), std::end(compVector), squRef);
if (iterator != std::end(compVector))
compVector.erase(iterator);
cout << "Vector size: " << compVector.size() << endl;
glutPostRedisplay();
}
创建组件时发生大量内存泄漏。您在堆上分配一个新组件,然后将其副本放入 std::vector
。作用域退出后,指向堆上新组件的指针将永远丢失。
只需在堆栈上创建组件,将它们添加到您的向量中就可以了。
此外,索引从 0 开始,而不是 1:
int Component::nextIndex = 1;
应该是
int Component::nextIndex = 0;
但这无论如何都是一个设计错误;当您从 std::vector
中删除组件时,您将必须更新 all 位于已删除组件之后的组件的索引(您需要将它们的值减 1 ).
如果你开始从迭代器而不是指针的角度思考会更好。我猜你想要以下内容:只是一个巨大的全局数据结构,所有组件都在其中。这可能是 std::list<Component> compList
。然后忘记管理索引和指针,到处使用 std::list<Component>::iterator
而不是 Component*
。删除组件是安全的,只需执行
void OGWindow::deleteSquare( std::list<Component>::iterator squPtr ) {
compList.erase(squPtr);
cout << "List size: " << compList.size() << endl;
glutPostRedisplay();
}
并添加组件
if (x >= createButtonX && x <= createButtonX + createButtonWidth) {
cout << "Clicked Create button" << endl;
Component comp;
comp.setX(0.0);
comp.setY(0.0);
// Notice how we put the new component at the front
// instead of the back.
compList.push_front(comp);
//------------SET THE CURRENT SQUARE TO THE NEWLY CREATED COMPONENT-----
// easy now!
currentSquarePtr = compList.begin();
cout << "List size: " << compList.size() << endl;
glutPostRedisplay();
}
记住,改变这些
Component *currentSquarePtr;
Component *linkSquPtr1;
Component *linkSquPtr2;
这些
std::list<Component>::iterator currentSquarePtr;
std::list<Component>::iterator linkSquPtr1;
std::list<Component>::iterator linkSquPtr2;
link 到项目 我正在创建一个将绘制电路组件的小型过剩应用程序。 我有一个名为 "Component" 的 class,看起来像这样:
// nextIndex is the index of the next component to be created
int Component::nextIndex = 0;
Component::Component( void ){
setType( RESISTOR );
setValue( 0.0 );
setX( 0.0 );
setY( 0.0 );
setSize( 2.0 );
setIndex( nextIndex );
}
eType Component::getType( void ){return cType}
double Component::getValue( void ){return cValue;}
double Component::getX( void ){return cX;}
double Component::getY( void ){return cY;}
double Component::getSize( void ){return cSize;}
void Component::setType( eType type ){cType = type;}
void Component::setValue( double value ){cValue = value;}
void Component::setX( double x){cX = x;}
void Component::setY( double y ){cY = y;}
void Component::setSize( double size ){cSize = size;}
int Component::getIndex( void ){return index;}
void Component::setIndex( int n ){index = n;}
注意:每次创建 class 的新实例时,我都会递增 nextIndex。 这是我的另一个 class,它有一个组件向量并处理组件的添加和删除:
class OGWindow{
private:
bool LINK, DELETE;
int linkNo;
...
Component currentSquare;
Component *currentSquarePtr, *linkSquPtr1, *linkSquPtr2;
double squareXStart, squareYStart, squareXEnd, squareYEnd;
std::vector< Component > compVector;
public:
...
void myMouseClick(int button, int state, int x, int y);
...
void deleteSquare( Component *squPtr );
};
我正在为 window 创建组件,就像这样: 整数 NEXT_INT = 0;
if (x >= createButtonX && x <= createButtonX + createButtonWidth) {
cout << "Clicked Create button" << endl;
Component *compPtr = new Component;
compPtr->setX(0.0);
compPtr->setY(0.0);
compPtr->setIndex(NEXT_INT);
NEXT_INT++;
compVector.push_back(*compPtr);
//------------SET THE CURRENT SQUARE TO THE NEWLY CREATED COMPONENT-----
vector<Component>::iterator constIterator;
for (constIterator = compVector.begin(); constIterator != compVector.end(); ++constIterator){
currentSquarePtr = &(*constIterator);
}
cout << "Vector size: " << compVector.size() << endl;
glutPostRedisplay();
}
但是当我删除时,它会删除一些元素,最后一个元素我得到 "vector out of range" 错误:
void OGWindow::deleteSquare( Component *squPtr ) {
compVector.erase(compVector.begin() + (squPtr->getIndex()));
cout << "Vector size: " << compVector.size() << endl;
glutPostRedisplay();
}
请分享发生这种情况的任何想法。
您对 Component
对象的索引存在一些问题。
首先,向量的索引类似于数组,即基于零。因此,如果您有一个仅包含一个元素的向量,则索引(以及距 begin()
迭代器的偏移量)为 zero。其他任何内容均超出范围。
您似乎有一个用于下一个索引的 static
成员变量,并且您将该变量初始化为 1
,这在向量中总是错误的第一个索引。然后在 Component
构造函数中你增加这个静态 nextIndex
变量导致你创建的第二个对象有索引 2
但在向量中它将有索引 1
(如果你有向量中的两个对象)。
从向量中删除对象时会出现另一个问题。除了使用错误索引的(现在很明显)问题之外,您不会对向量中的索引重新编号。因此,如果向量中有两个元素具有(错误的)索引 1
和 2
,并删除第一个元素,那么新的第一个元素将具有更错误的索引 2
.
我解决这个问题的建议是完全不使用索引,而是实现一个比较运算符来实现相等性。然后你可以使用例如std::find
找到向量中的对象,然后用 std::find
.
erase
那么 deleteSquare
看起来像
void OGWindow::deleteSquare( Component const &squRef ) {
auto iterator = std::find( std::begin(compVector), std::end(compVector), squRef);
if (iterator != std::end(compVector))
compVector.erase(iterator);
cout << "Vector size: " << compVector.size() << endl;
glutPostRedisplay();
}
创建组件时发生大量内存泄漏。您在堆上分配一个新组件,然后将其副本放入 std::vector
。作用域退出后,指向堆上新组件的指针将永远丢失。
只需在堆栈上创建组件,将它们添加到您的向量中就可以了。
此外,索引从 0 开始,而不是 1:
int Component::nextIndex = 1;
应该是
int Component::nextIndex = 0;
但这无论如何都是一个设计错误;当您从 std::vector
中删除组件时,您将必须更新 all 位于已删除组件之后的组件的索引(您需要将它们的值减 1 ).
如果你开始从迭代器而不是指针的角度思考会更好。我猜你想要以下内容:只是一个巨大的全局数据结构,所有组件都在其中。这可能是 std::list<Component> compList
。然后忘记管理索引和指针,到处使用 std::list<Component>::iterator
而不是 Component*
。删除组件是安全的,只需执行
void OGWindow::deleteSquare( std::list<Component>::iterator squPtr ) {
compList.erase(squPtr);
cout << "List size: " << compList.size() << endl;
glutPostRedisplay();
}
并添加组件
if (x >= createButtonX && x <= createButtonX + createButtonWidth) {
cout << "Clicked Create button" << endl;
Component comp;
comp.setX(0.0);
comp.setY(0.0);
// Notice how we put the new component at the front
// instead of the back.
compList.push_front(comp);
//------------SET THE CURRENT SQUARE TO THE NEWLY CREATED COMPONENT-----
// easy now!
currentSquarePtr = compList.begin();
cout << "List size: " << compList.size() << endl;
glutPostRedisplay();
}
记住,改变这些
Component *currentSquarePtr;
Component *linkSquPtr1;
Component *linkSquPtr2;
这些
std::list<Component>::iterator currentSquarePtr;
std::list<Component>::iterator linkSquPtr1;
std::list<Component>::iterator linkSquPtr2;