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

Можно ли удалить элемент из std::list, если у вас есть только итератор, который указывает на элемент, который вы хотите удалить? У меня есть большое количество функций, которые принимают итераторы для перечисления элементов, и было бы огромным неудобством передавать принадлежащий list каждому из них.

Ответы [ 6 ]

3 голосов
/ 30 июля 2011

Вы не можете сделать это со стандартной библиотекой, но вы можете использовать навязчивый список Boost http://www.boost.org/doc/libs/1_37_0/doc/html/boost/intrusive/list.html, который имеет такой интерфейс.

3 голосов
/ 30 июля 2011

Нет, вы не можете. Итераторы - это легковесные объекты, смоделированные после указателей, и не содержат ссылки на контейнер, на который они ссылаются. (Хотя некоторые реализации делают это внутренне в режиме отладки.)

Так же, как вы не можете «удалить» объект из массива, когда у вас есть только указатель на массив, вы не можете удалить объект из контейнера, не имея также доступа к контейнеру.

3 голосов
/ 30 июля 2011

Edit:

Вы не можете использовать один итератор.

Если у вас есть итераторы начала / конца, вы можете использовать алгоритм std::remove, чтобы переместить все элементы, которые вы хотите стереть, в конец и удалить их на более позднем этапе.

Если вы этого не сделаете, или вышеприведенное невозможно с вашим текущим дизайном, я бы порекомендовал изменить ваши функции на std::pair<std::list<T>, std::list<T>::iterator> или что-то в этом роде.

1 голос
/ 04 августа 2011

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

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

По этой причине любой предложенный хак, скорее всего, потерпит неудачу.

0 голосов
/ 30 июля 2011

Вы можете сделать это вручную.итератор выставляет _M_node в качестве текущего узла.Вы можете сделать что-то вроде:

itr._M_node->_M_prev->_M_next = itr._M_node._M_next;
0 голосов
/ 30 июля 2011

Нет, это невозможно.Как следует из названия, работа итератора состоит в том, чтобы перебирать элементы последовательности.Посетите страницу SGI по итераторам , чтобы получить сводную информацию о дизайне итераторов в стандартной библиотеке C ++.

...