Стирание вектор :: конец из вектора - PullRequest
30 голосов
/ 06 марта 2012

Работает ли правильно (ничего не делает), когда я использую

 vector<T> v;
 v.erase(v.end());

Я хочу использовать что-то вроде

 v.erase(std::find(...));

Должен ли я if это v.end() или нет?
Нет информации об этом на C ++. Com и CPPreference

Ответы [ 3 ]

24 голосов
/ 06 марта 2012

Стирание end() (или даже если посмотреть на цель end()) - неопределенное поведение.Неопределенное поведение может иметь любое поведение, в том числе «просто работать» на вашей платформе.Это не значит, что вы должны это делать;это все еще неопределенное поведение, и я приду к вам наихудшим образом, когда вы меньше всего этого ожидаете позже.

В зависимости от того, что вы делаете, вы можете рассмотреть set или unordered_set вместо vector здесь.

24 голосов
/ 06 марта 2012

Стандарт не совсем разъясняет это, но v.erase(q) определено, "Стирает элемент, на который указывает q" в [sequence.reqmts]. Это означает, что q должен фактически указывать на элемент, а конечный итератор - нет. Передача в конце итератора - неопределенное поведение.

К сожалению, вам нужно написать:

auto it = std::find(...);
if (it != <the part of ... that specifies the end of the range searched>) {
    v.erase(it);
}

Конечно, вы можете определить:

template typename<Sequence, Iterator>
Iterator my_erase(Sequence &s, Iterator it) {
    if (it == s.end()) return it;
    return s.erase(it);
}

my_erase(v, std::find(v.begin(), v.end(), whatever));

c.erase() в ассоциативном контейнере возвращает void, поэтому, чтобы обобщить этот шаблон для всех контейнеров, вам понадобится какое-то действие -> decltype.

5 голосов
/ 06 марта 2012

Вы пробовали это?

v.erase(remove_if(v.begin(), v.end(), (<your criteria>)), v.end());
...