2013-02-27 4 views
7

Мне нужно удалить элемент из std::list после поиска std::find. Каково поведение вызова std::list::erase с end() списка? Мой случай что-то вроде этого:Каково поведение стирания `end()` `std :: list`?

std::list<T> mylist; 
T value; 
std::list::iterator it = std::find(mylist.begin(), mylist.end(), value); 
std::list::iterator next = mylist.erase(it); 

cplusplus.com говорит:

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

, но я не знаю, является ли end() действительным.

+0

'end()' один за последним элементом. –

+0

cplusplus.com также выходит за рамки авторитетных источников. Вместо этого смотрите cppreference.com. – Potatoswatter

+0

@Potatoswatter: Интернет находится за пределами авторитетных источников. См. Спецификацию языка. –

ответ

17

Этот сайт использует неопределенный (и, возможно, неверный) термин «действительный», но спецификация библиотеки (C++ 11 23.2.3) использует более конкретный термин «разыменованный» - это означает, что итератор должен относиться к объекту. Итератор прошедшего конца не является разборным, поэтому его удаление дает неопределенное поведение.

+3

+1, также я думаю, что в Интернете есть худшая проблема, чем быть * неопределенной *, поскольку 'valid' - это термин, который используется в стандарте, и' end() 'дает * valid * iterator (т. е. веб-страница не * неопределенная *, это ** неправильно **) –

+0

На самом деле в спецификации библиотеки также используется «valid» (например, для вставки, где 'end()' -Iterator ok), но он явно говорит «valid * and * dereferencable» как требование для стирания с одним итератором. –

+0

Спасибо! Это то, что я искал. У меня нет доступа к спецификации. Знаете ли вы, что в C++ 03 одинаково? – Janoma

6

Это не так. Попытка стереть end() приводит к неопределенному поведению.

2

end() Возвращает итератор, ссылающийся на итератор прошедшего конца в контейнер списка, а не последний объект в списке.

Удаляя/стирая конец, вы удаляете вне диапазона своего списка. Ваш код должен быть:

std::list<T> mylist; 
T value; 
std::list::iterator it = std::find(mylist.begin(), mylist.end(), value); 
If(it!=mylist.end()) 
    std::list::iterator next = mylist.erase(it); 

Кроме того, если находка() не может найти значение в списке будет возвращать конечный итератор, это в основном говорит вам, что значение, которое вы ищете, находится за пределами вашего списка (нет в списке)

+0

В контейнере нет сквозного элемента. 'end()' возвращает конечный ** итератор **. В общем, итератор, прошедший в конце, не должен ссылаться на элемент, хотя во многих ситуациях он фактически это делает. –

+0

Исправлено, не нужно быть сумасшедшим –

+0

Mad? Надеюсь, я так не попал. –

Смежные вопросы