Удаление пользовательских элементов в середине вектора - PullRequest
5 голосов
/ 01 апреля 2011

Я пишу программу, в которой я хочу нарисовать карту, а затем удалить ее, чтобы она больше не рисовалась.

У меня есть вектор карт (класс, содержащий 2 структуры, которые определяют Suitи Value) называется колода, и я не очень хорошо знаю, как использовать итераторы, вот фрагмент кода:

void Player::discardCard(CardDeck masterDeck)
{
    cout << "Erasing: " << masterDeck.getDeck().at(cardSelect).toString() << endl;
    /*Attempt1*/
    masterDeck.getDeck().erase(masterDeck.getDeck().begin()+cardSelect);

    /*Attempt 2*/
    vector<Card>::iterator itr;
    itr = masterDeck.getDeck().begin() + cardSelect;
    masterDeck.getDeck().erase(itr);
}

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

Каждый раз, когда я компилирую, я получаю следующую ошибку:

"Expression: vector erase iterator outside range"

Я действительно не знаю, что делать, надеюсь, кто-нибудьможете мне помочь, заранее спасибо!

Ответы [ 3 ]

1 голос
/ 01 апреля 2011

Моя ставка в том, что getDeck возвращает вектор по значению. Это заставляет itr указывать и erase работать с различными копиями вектора. Таким образом вы получите ошибку. Вы должны вернуть вектор по ссылке. Измените getDeck подпись на эту:

vector<Card>& getDeck()
1 голос
/ 01 апреля 2011

Позвольте мне сначала уйти от темы. Ваш дизайн немного подозрительный. Первый переход в CardDeck по значению почти наверняка не то, что вы хотите, но это даже не относится к делу. Почему в вашем классе Player должно быть все это внутреннее знание о частных внутренностях CardDeck. Не должно заботиться о том, чтобы вы хранили колоду как вектор или деку (ха-ха), или какова структура. Это просто не должно знать это. Все, что он знает, это то, что он хочет сбросить карту.

masterDeck.Discard (selectedCard);

Также обратите внимание, что selectedCard должен быть между 0 и ONE LESS размера колоды, но даже это, вероятно, не ваша проблема (хотя это будет 1/53 времени)

Итак, чтобы ответить на ваш вопрос, нам действительно нужно немного подробнее рассказать о masterDeck. Вы реализовали правильный пользовательский конструктор копирования? Поскольку вы передаете по значению шансов, вы не правильно копируете базовый вектор, на самом деле он, вероятно, пуст и ни одно из удалений не будет работать. Попробуйте проверить размер. Если вы никогда не хотите, чтобы колода была скопирована, вы можете позволить компилятору помочь вам, объявив конструктор частной копии, а затем никогда не определяя его. См. Эффективный C ++ Скотта Мейера, пункт 11.

Наконец, последний совет, я полагаю, что после того, как вы удалите его с помощью итератора, вы сделаете его недействительным. Вектор может быть перераспределен (почти наверняка, если вы удалите его где-нибудь, кроме конца). Я просто говорю вам, чтобы вы не пытались вызвать стирание более одного раза на одном итераторе. Одна из хитростей в итераторах заключается в том, насколько легко их можно аннулировать, поэтому вы часто видели проверки на iter! = Coll.end ().

0 голосов
/ 01 апреля 2011

«Он генерируется случайным образом в пределах от 0 до размера колоды».

Допустимый диапазон должен быть «между 0 и размером колоды минус 1».Это может привести к ошибке диапазона во время выполнения.

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