Стирание элемента из вектора во время итерации c ++ - PullRequest
1 голос
/ 08 октября 2010

Я написал этот метод, чтобы найти минор разреженной матрицы:

SpMatrixVec SparseMatrix::minor(SpMatrixVec matrix, int col) const{

    SpMatrixVec::iterator it = matrix.begin();

    int currRow = it->getRow();

    int currCol = col;

    while(it != matrix.end()) {

        if(it->getRow() == currRow || it->getCol() == currCol){
            matrix.erase(it);
        }
        // if we have deleted an element in the array, it doesn't advance the
        // iterator and size() will be decreased by one.
        else{   
            it++;
        }

    }

    // now, we alter the cells of the minor matrix to be of proper coordinates.
    // this is necessary for sign computation (+/-) in the determinant recursive
    // formula of detHelper(), since the minor matrix non-zero elements are now
    // in different coordinates. The row is always decreased by one, since we
    // work witht he first line, and the col is decreased by one if the element
    // was located after 'col' (which this function receives as a parameter).

    //change the cells of the minor to their proper coordinates.
    for(it = matrix.begin(); it != matrix.end(); it++){

        it->setRow(it->getRow()-1);

        int newY;
        newY = (it->getCol() > col) ? it->getCol() + 1 : it->getCol();

        it->setCol(newY);
    }
    return matrix;

}

Теперь я, вероятно, что-то делаю не так, потому что при достижении второго целого числа цикла while программасбои.Основная идея состояла в том, чтобы пройтись по вектору и посмотреть, является ли это соответствующей координатой, и если да, то удалить ее.Я увеличиваю значение итератора только в том случае, если не было удаления (и в этом случае вектор должен обновить итератор, чтобы он указывал на следующий элемент ... если только я не ошибся).

В чем проблема?

Большое спасибо.

Ответы [ 3 ]

9 голосов
/ 08 октября 2010

erase() делает недействительным ваш итератор.

Необходимо обновить it, используя возвращаемое значение erase(), чтобы цикл работал:

while(it != matrix.end()) {

    if(it->getRow() == currRow || it->getCol() == currCol){
        //matrix.erase(it);
        it = matrix.erase(it); // Here is the change
    }
    // if we have deleted an element in the array, it doesn't advance the
    // iterator and size() will be decreased by one.
    else{   
        //it++;
        ++it; // ++i is usually faster than i++. It's a good habit to use it.
    }

}
5 голосов
/ 08 октября 2010

erase делает недействительным ваш итератор. Делай it = matrix.erase(it) вместо.

0 голосов
/ 08 октября 2010

Вы не можете изменить коллекцию, пока вы перебираете ее элементы. Используйте другую временную коллекцию для хранения частичных результатов.

edit: еще лучше использовать функтор для удаления элементов: remove_if Вы пишете условие.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...