Форум программистов, компьютерный форум CyberForum.ru

На что ссылается итератор после remove(*it) - C++

Восстановить пароль Регистрация
 
Red Planet
 Аватар для Red Planet
49 / 10 / 2
Регистрация: 20.09.2009
Сообщений: 263
29.03.2012, 21:11     На что ссылается итератор после remove(*it) #1
Здравствуйте! Не понимаю, почему итератор ссылается на удаленный из списка элемент?

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#include <vcl>
#include <iostream>
#include <fstream>
#include <list>
#include <vector>
#include <string>
 
using namespace std;
 
 
 
// -----------------------------------------------------------------------------
int _tmain(int argc, _TCHAR* argv[]) {
    list<int> mylist;
    list<int>::iterator it1;
 
    for (int i = 1; i < 10; i++)
        mylist.push_back(i * 10);
 
    it1 = mylist.begin();
    it1++;
 
    while (*it1 < 70) {
        int it1_value = *it1;
        cout << "Before: " << it1_value << endl;
 
        mylist.remove(*it1);
 
        it1_value = *it1;
        cout << "After: " << it1_value << endl;
        it1++;
    }
 
    it1 = mylist.begin();
    cout << endl;
    for (;  it1 != mylist.end(); it1++)
        cout << *it1 << " " ;
    cout << endl;
    system("pause");
    return 0;
}
Вывод показывает, что после удаления элемента из списка и применения

C++
1
it1_value = *it1;
it1_value станет равным значению удаленного элемента. Его же (элемента) не существует. Нелогично.
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
antoha398
155 / 155 / 3
Регистрация: 29.03.2012
Сообщений: 418
29.03.2012, 21:21     На что ссылается итератор после remove(*it) #2
Получается, что элемент удален только из списка, а в памяти он остался и итератор по прежнему содержит адрес памяти.
villu
202 / 202 / 4
Регистрация: 06.08.2011
Сообщений: 600
Записей в блоге: 1
29.03.2012, 21:59     На что ссылается итератор после remove(*it) #3
после удаления из листа его итератор вообще становится невалидным.
так что код
C++
1
2
it1_value = *it1;
cout << "After: " << it1_value << endl;
невалидный и опасный.
ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 3
29.03.2012, 23:43     На что ссылается итератор после remove(*it) #4
villu, А это откуда взято интересно? Все несколько проще подозреваю.
Removes from the list all the elements with a specific value. This calls the destructor of these objects and reduces the list size by the amount of elements removed.
Notice that a global algorithm function, remove, exists with a similar behavior but operating between two iterators.
А std::remove не делает ничего иного, кроме как перемещает элемент в конец и возвращает итератор на начало удаленных элементов.
villu
202 / 202 / 4
Регистрация: 06.08.2011
Сообщений: 600
Записей в блоге: 1
30.03.2012, 00:02     На что ссылается итератор после remove(*it) #5
list::remove это не std::remove и делает не тоже самое.
ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 3
30.03.2012, 00:09     На что ссылается итератор после remove(*it) #6
villu,
Notice that a global algorithm function, remove, exists with a similar behavior but operating between two iterators.
Я как бэ цитату для кого привел?
villu
202 / 202 / 4
Регистрация: 06.08.2011
Сообщений: 600
Записей в блоге: 1
30.03.2012, 00:11     На что ссылается итератор после remove(*it) #7
да, не там прочитал.
Но итератор после удаления все равно становится невалидным.
ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 3
30.03.2012, 00:21     На что ссылается итератор после remove(*it) #8
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
    void remove(const _Ty& _Val_arg)
        {   // erase each element matching _Val
        const _Ty _Val = _Val_arg;  // in case it's removed along the way
        const _Nodeptr _Phead = this->_Myhead;
        _Nodeptr _Pnode = this->_Nextnode(_Phead);
 
        while (_Pnode != _Phead)
            if (_Pnode->_Myval == _Val)
                {   // match, remove it
                const _Nodeptr _Pprev = this->_Prevnode(_Pnode);
                const _Nodeptr _Perase = _Pnode;
                _Pnode = this->_Nextnode(_Pnode);
 
                this->_Nextnode(_Pprev) = _Pnode;
                this->_Prevnode(_Pnode) = _Pprev;
                this->_Freenode(_Perase);
 
                --this->_Mysize;
                }
            else
                _Pnode = this->_Nextnode(_Pnode);
        }
Реализация из студии.
Но то, что использоваться это не стоит и что при первом же изменении итератор станет недействительным согласен.

Добавлено через 4 минуты
Признаю свою неправоту.
15 Effects: Erases all the elements in the list referred by a list iterator i for which the following conditions
hold: *i == value, pred(*i) != false. Invalidates only the iterators and references to the erased
elements.
16 Throws: Nothing unless an exception is thrown by *i == value or pred(*i) != false.
17 Remarks: Stable.
18 Complexity: Exactly size() applications of the corresponding predicate.
villu
202 / 202 / 4
Регистрация: 06.08.2011
Сообщений: 600
Записей в блоге: 1
30.03.2012, 00:28     На что ссылается итератор после remove(*it) #9
ну так об этом и была речь. Никуда он (list::remove) ничего не двигает, просто удаляет и меняет указатели.
это к
А std::remove не делает ничего иного, кроме как перемещает элемент в конец и возвращает итератор на начало удаленных элементов.
а вот он (std::remove) как раз делает очень по тупому и неэффективно, сдвигая элементы на место удаленных.
silent_1991
Эксперт C++
4938 / 3014 / 149
Регистрация: 11.11.2009
Сообщений: 7,024
Завершенные тесты: 1
30.03.2012, 19:07     На что ссылается итератор после remove(*it) #10
Цитата Сообщение от villu Посмотреть сообщение
а вот он (std::remove) как раз делает очень по тупому и неэффективно, сдвигая элементы на место удаленных.
Т.е. было бы эффективнее перевыделить память и скопировать в неё все нужные элементы? (применительно к вектору, например). Или речь велась исключительно о списках?
villu
202 / 202 / 4
Регистрация: 06.08.2011
Сообщений: 600
Записей в блоге: 1
30.03.2012, 21:16     На что ссылается итератор после remove(*it) #11
ну про список же говорили. для списка std::remove не эффективен. и не только для списка
Т.е. было бы эффективнее перевыделить память и скопировать в неё все нужные элементы?
а вот именно так и делает другой алгоритм (копирует только нужное в смысле).
Red Planet
 Аватар для Red Planet
49 / 10 / 2
Регистрация: 20.09.2009
Сообщений: 263
31.03.2012, 20:59  [ТС]     На что ссылается итератор после remove(*it) #12
Цитата Сообщение от villu Посмотреть сообщение
std::remove не эффективен
Кстати, есть небольшая статья по нему. Сам был удивлен, когда прочитал, что алгоритм remove не совсем удаляет элементы.
silent_1991
Эксперт C++
4938 / 3014 / 149
Регистрация: 11.11.2009
Сообщений: 7,024
Завершенные тесты: 1
31.03.2012, 21:03     На что ссылается итератор после remove(*it) #13
Red Planet, чтобы "совсем удалял", нужно использовать erase-remove idiom.
alex_x_x
бжни
 Аватар для alex_x_x
2441 / 1646 / 84
Регистрация: 14.05.2009
Сообщений: 7,163
31.03.2012, 21:06     На что ссылается итератор после remove(*it) #14
Цитата Сообщение от Red Planet Посмотреть сообщение
Кстати, есть небольшая статья по нему. Сам был удивлен, когда прочитал, что алгоритм remove не совсем удаляет элементы.
алгоритм не может удалять элементы контейнера, так как удаление не очень общая операция
так что на самом деле это логичное решение
Red Planet
 Аватар для Red Planet
49 / 10 / 2
Регистрация: 20.09.2009
Сообщений: 263
31.03.2012, 21:16  [ТС]     На что ссылается итератор после remove(*it) #15
silent_1991, насчет erase-remove idiom. Использование этого необходимо если мы имеем дело с вектором и используем алгоритм STL. В моей задаче нужно удалить из списка, то есть достаточно будет воспользоваться

C++
1
mylist.erase(it_from_incl, it_to_not_incl);
Добавлено через 56 секунд
Цитата Сообщение от alex_x_x Посмотреть сообщение
алгоритм не может удалять элементы контейнера, так как удаление не очень общая операция
так что на самом деле это логичное решение
Согласен.
silent_1991
Эксперт C++
4938 / 3014 / 149
Регистрация: 11.11.2009
Сообщений: 7,024
Завершенные тесты: 1
31.03.2012, 21:17     На что ссылается итератор после remove(*it) #16
Red Planet, разумеется. разговор ведь шёл об std::remove.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
31.03.2012, 21:24     На что ссылается итератор после remove(*it)
Еще ссылки по теме:

Не правильно работает erase + remove C++
Как проверить на какой класс ссылается указатель? C++
Указатель в списке ссылается на себя, а не на следующий элемент C++

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
Red Planet
 Аватар для Red Planet
49 / 10 / 2
Регистрация: 20.09.2009
Сообщений: 263
31.03.2012, 21:24  [ТС]     На что ссылается итератор после remove(*it) #17
Вопрос закрыт. Благодарю всех участвовавших в обсуждении.
Yandex
Объявления
31.03.2012, 21:24     На что ссылается итератор после remove(*it)
Ответ Создать тему
Опции темы

Текущее время: 16:17. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru