Форум программистов, компьютерный форум, киберфорум
Наши страницы
С++ для начинающих
Войти
Регистрация
Восстановить пароль
 
 
Рейтинг 5.00/12: Рейтинг темы: голосов - 12, средняя оценка - 5.00
rikimaru2013
2516 / 1178 / 355
Регистрация: 30.11.2013
Сообщений: 3,792
1

Изменение контейнера во время итерационного перебора

11.09.2016, 21:20. Просмотров 2257. Ответов 100
Метки нет (Все метки)

Добрый вечер,

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
void Add( Some* ptr )
{
    cont.push_back( ptr );
}
void Update()
{
    for ( auto it = std::begin( cont ); it != std::end( cont ); )
    {
        ( *it )->Update();
        if ( ( *it )->Finished() )
        {
            it = cont.erase( it );
        }
        else
        {
            ++it;
        }
    }
}
Если в Update как-то запушить в cont - то итератор не валиден по понятным причинам, как и ++it. Пришлось извращаться:
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
void Add( Some* ptr )
{
    if(_protect)
        delay.push_back(ptr)
    else
        cont.push_back( ptr );
}
void Update()
{
    _protect = true;
    for ( auto it = std::begin( cont ); it != std::end( cont ); )
    {
        ( *it )->Update();
        if ( ( *it )->Finished() )
        {
            it = cont.erase( it );
        }
        else
        {
            ++it;
        }
    }
    _protect = false;
    PushAllDelayToContAndClear();
}
Подскажите, есть ли методики не писать такие костыли? Или концептуально вы скажите не правильно, что некий тип умеет пушить в родителя?
0
QA
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
11.09.2016, 21:20
Ответы с готовыми решениями:

Время выполнения рекурсивного и итерационного алгоритма быстрой сортировки
Почему вот это : void sort(int *ar, int L, int R){ int i, j, x, buf; x = ar; i =...

Определить время перебора всех паролей с параметрами
Определить время перебора всех паролей с параметрами. Алфавит состоит из n символов. Длина...

Посчитать время полного перебора всех паролей
Задача такая: есть пароль из 15 символов,состоящий из A-z = 52 + знаки (я насчитал 32) Есть сервер...

Изменение z-index контейнера из выполняемого скрипта
К празднику (23-е февраля) понадобилось создать на сайте проезжающий внизу страницы время от...

Удаление из контейнера элемента и изменение его размеров
textList = new ArrayList<>(); //... textList.remove(textList.size()-1); Почему после выполнения...

100
Fulcrum_013
Заблокирован
11.09.2016, 21:43 2
Ну если тут просто удаление то можно просто идти в реверсном направлении. Т.е. с конца к началу. Тогда при удалении порядок обхода не изменяется.
0
Avazart
Эксперт С++
7965 / 5787 / 571
Регистрация: 10.12.2010
Сообщений: 26,607
Записей в блоге: 17
11.09.2016, 21:45 3
Обходить/удалять элементы вектора с конца.
0
Fulcrum_013
Заблокирован
11.09.2016, 21:50 4
Лучший ответ Сообщение было отмечено rikimaru2013 как решение

Решение

rikimaru2013 При этом если это вектор и в процессе кроме удаления есть добавления пользовать не итераторы а индексы. Они остаются валидными при реаллоке.,
1
11.09.2016, 21:50
rikimaru2013
2516 / 1178 / 355
Регистрация: 30.11.2013
Сообщений: 3,792
11.09.2016, 22:24  [ТС] 5
Там же Add/push - то есть реалок вектора в худчем случаи, в лучшем всё ок)

Добавлено через 2 минуты
Fulcrum_013, вместо (*it) использовать cont[i] повсюду?
0
ct0r
Игогошка!
1797 / 704 / 44
Регистрация: 19.08.2012
Сообщений: 1,365
Завершенные тесты: 1
11.09.2016, 22:27 6
Цитата Сообщение от rikimaru2013 Посмотреть сообщение
Подскажите, есть ли методики не писать такие костыли?
Есть такая методика - не писать говнокод

Цитата Сообщение от rikimaru2013 Посмотреть сообщение
Или концептуально вы скажите не правильно, что некий тип умеет пушить в родителя?
А ты сам-то как думаешь? Где твои рассуждения?
0
rikimaru2013
2516 / 1178 / 355
Регистрация: 30.11.2013
Сообщений: 3,792
11.09.2016, 22:38  [ТС] 7
Цитата Сообщение от ct0r Посмотреть сообщение
А ты сам-то как думаешь? Где твои рассуждения?
злой такой - пришёл накричал ушёл (((( Я думаю там всё ок - и нарушение IoC это малое, на что идут люди)
0
ct0r
Игогошка!
1797 / 704 / 44
Регистрация: 19.08.2012
Сообщений: 1,365
Завершенные тесты: 1
11.09.2016, 23:00 8
Цитата Сообщение от rikimaru2013 Посмотреть сообщение
Я думаю там всё ок
Это ты в (*it)->Update() можешь что-то запушить в контейнер, я так понял? Или нет?
Представь, что видишь код Update() впервые. Тебе сразу очевидно из кода, что делает цикл - а именно в каком состоянии будет контейнер после его выполнения?
А теперь представь, что надо что-то зарефакторить. Насколько приятно это делать с твоим Update?

Цитата Сообщение от rikimaru2013 Посмотреть сообщение
и нарушение IoC это малое, на что идут люди)
Ради чего идут?
0
Fulcrum_013
Заблокирован
11.09.2016, 23:06 9
Цитата Сообщение от rikimaru2013 Посмотреть сообщение
вместо (*it) использовать cont[i] повсюду?
Ну да. У меня правда для таких дел пользуются заточенные под это контейнеры с выпиливаемым в релизе range-checking.

Добавлено через 4 минуты
Цитата Сообщение от ct0r Посмотреть сообщение
Ради чего идут?
К примеру ради сокращения кода в несколько раз.
Цитата Сообщение от ct0r Посмотреть сообщение
А теперь представь, что надо что-то зарефакторить. Насколько приятно это делать с твоим Update?
Поэтому такие дела обычно выносят под капот специальных контейнеров и абстрактят так, чтобы очень долго не рефакторить.
0
Avazart
Эксперт С++
7965 / 5787 / 571
Регистрация: 10.12.2010
Сообщений: 26,607
Записей в блоге: 17
11.09.2016, 23:12 10
Цитата Сообщение от rikimaru2013 Посмотреть сообщение
Fulcrum_013, вместо (*it) использовать cont[i] повсюду?
Зачем?
0
Nosey
1376 / 403 / 144
Регистрация: 22.10.2014
Сообщений: 872
Завершенные тесты: 2
11.09.2016, 23:24 11
Цитата Сообщение от rikimaru2013 Посмотреть сообщение
есть ли методики не писать такие костыли
1) init + update
2) расширенная версия : init+ invalidate + validate + update (с учетом зависимостей дитя-родитель), либо юзать умные указатели.
3) оставить костыль если этот код локальный.
1
hoggy
Эксперт С++
7407 / 3333 / 689
Регистрация: 15.11.2014
Сообщений: 7,618
Завершенные тесты: 1
11.09.2016, 23:25 12
Лучший ответ Сообщение было отмечено rikimaru2013 как решение

Решение

Цитата Сообщение от rikimaru2013 Посмотреть сообщение
Подскажите, есть ли методики не писать такие костыли?
обычно делают так:
есть два контейнера.
один для новеньких.
другой для стареньких.

рабочий конвейер последовательно обновляет стареньких.
дети не могут никак влиять на контейнер.
они могут лишь возвращать собственный статус:
"я активен", "я свободен", "я завершился", и тп.

если апдейт приводит к рождению нового ребенка,
то он добавляется в контейнер новеньких.

потом, когда пробег по контейнеру стареньких завершается,
родитель перемещает новеньких к стареньким.
1
rikimaru2013
11.09.2016, 23:25  [ТС]
  #13

Не по теме:

Цитата Сообщение от Nosey Посмотреть сообщение
оставить костыль
я знал, что он тебе понравится - красивый такой :yahoo:

0
Fulcrum_013
Заблокирован
11.09.2016, 23:26 14
Цитата Сообщение от Avazart Посмотреть сообщение
Зачем?
Затем что у него кроме удаления еще и добавление. Если при этом добавлении вектор реалокнется итератор станет невалидным в отличии от индекса.
0
rikimaru2013
2516 / 1178 / 355
Регистрация: 30.11.2013
Сообщений: 3,792
11.09.2016, 23:26  [ТС] 15
hoggy, ну то бишь мой костыль и есть то о чём вы советуете:?
0
Fulcrum_013
Заблокирован
11.09.2016, 23:29 16
Цитата Сообщение от hoggy Посмотреть сообщение
дети не могут никак влиять на контейнер
Далеко не всегда такое поведение является оптимальным.
0
Avazart
Эксперт С++
7965 / 5787 / 571
Регистрация: 10.12.2010
Сообщений: 26,607
Записей в блоге: 17
11.09.2016, 23:30 17
Цитата Сообщение от Fulcrum_013 Посмотреть сообщение
Если при этом добавлении вектор реалокнется итератор станет невалидным в отличии от индекса.
Какой итератор?
Add и Update не могут же выполнятся одновременно.
0
rikimaru2013
2516 / 1178 / 355
Регистрация: 30.11.2013
Сообщений: 3,792
11.09.2016, 23:30  [ТС] 18
Fulcrum_013, кстати это работает только при гарантии add_only - ведь при обращению по индексу

C++
1
2
3
const int index = 4;
cont[i]->Update();
cont[i]->Finished();
Есть вероятность, что строка 2 и 3 будут работать с разными сущностями.
0
Nosey
1376 / 403 / 144
Регистрация: 22.10.2014
Сообщений: 872
Завершенные тесты: 2
11.09.2016, 23:33 19
Цитата Сообщение от rikimaru2013 Посмотреть сообщение
я знал, что он тебе понравится - красивый такой
Ну дык, другие варианты, этоже тоже самое только приправлены ООП, что добавит расширяемости, строгости, сложности, если это не нужно в первом приближении и завязаностей на этот код будет очень мало, то ..., ну вы поняли
1
rikimaru2013
2516 / 1178 / 355
Регистрация: 30.11.2013
Сообщений: 3,792
11.09.2016, 23:33  [ТС] 20
Цитата Сообщение от Avazart Посмотреть сообщение
Add и Update не могут же выполнятся одновременно.
Тема как раз об этом. Что было нарушено IoC и через синглтон пушиться в вектор дополнительный элемент
0
11.09.2016, 23:33
Answers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
11.09.2016, 23:33

Изменение содержимого контейнера при переключении радиокнопки
Имеется товар в интернет-магазине. у него несколько модификаций, которые выбираются через...

Изменение содержимого контейнера при переключении радиокнопки
Имеется товар в интернет-магазине. у него несколько модификаций, которые выбираются через...

Игра 2048: Как замедлить время перебора квадратов примерно до 0.4 секунды за ход?
Есть программа, она для игры 2048. Сама автоматом перебирает квадраты очень быстро за милисекунды....


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

Или воспользуйтесь поиском по форуму:
20
Закрытая тема Создать тему
Опции темы

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