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

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
Red Planet
49 / 10 / 2
Регистрация: 20.09.2009
Сообщений: 263
#1

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

29.03.2012, 21:11. Просмотров 866. Ответов 16
Метки нет (Все метки)

Здравствуйте! Не понимаю, почему итератор ссылается на удаленный из списка элемент?

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 станет равным значению удаленного элемента. Его же (элемента) не существует. Нелогично.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
29.03.2012, 21:11     На что ссылается итератор после remove(*it)
Посмотрите здесь:

C++ как создать копию объекта, на который ссылается итератор?
C++ stl remove своя функция
C++ Функция remove() удаляет только заранее запланированые файлы, выдавая ошибку на remove (STRING)
Функция возвращает не ссылку а само значение переменной на которое оно ссылается C++
C++ Получить адрес памяти, на который ссылается указатель
Не правильно работает erase + remove C++
Двусвязный список с целыми числами - Указатель, который ссылается на предыдущий блок C++
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
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
Модератор
Эксперт С++
7958 / 4720 / 319
Регистрация: 24.06.2010
Сообщений: 10,525
Завершенные тесты: 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
Модератор
Эксперт С++
7958 / 4720 / 319
Регистрация: 24.06.2010
Сообщений: 10,525
Завершенные тесты: 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
Модератор
Эксперт С++
7958 / 4720 / 319
Регистрация: 24.06.2010
Сообщений: 10,525
Завершенные тесты: 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
Эксперт С++
4956 / 3032 / 149
Регистрация: 11.11.2009
Сообщений: 7,027
Завершенные тесты: 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
49 / 10 / 2
Регистрация: 20.09.2009
Сообщений: 263
31.03.2012, 20:59  [ТС]     На что ссылается итератор после remove(*it) #12
Цитата Сообщение от villu Посмотреть сообщение
std::remove не эффективен
Кстати, есть небольшая статья по нему. Сам был удивлен, когда прочитал, что алгоритм remove не совсем удаляет элементы.
silent_1991
Эксперт С++
4956 / 3032 / 149
Регистрация: 11.11.2009
Сообщений: 7,027
Завершенные тесты: 1
31.03.2012, 21:03     На что ссылается итератор после remove(*it) #13
Red Planet, чтобы "совсем удалял", нужно использовать erase-remove idiom.
alex_x_x
бжни
2445 / 1650 / 84
Регистрация: 14.05.2009
Сообщений: 7,162
31.03.2012, 21:06     На что ссылается итератор после remove(*it) #14
Цитата Сообщение от Red Planet Посмотреть сообщение
Кстати, есть небольшая статья по нему. Сам был удивлен, когда прочитал, что алгоритм remove не совсем удаляет элементы.
алгоритм не может удалять элементы контейнера, так как удаление не очень общая операция
так что на самом деле это логичное решение
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
Эксперт С++
4956 / 3032 / 149
Регистрация: 11.11.2009
Сообщений: 7,027
Завершенные тесты: 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)
Еще ссылки по теме:

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

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

Или воспользуйтесь поиском по форуму:
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)
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru