Этот баннер — требование Роскомнадзора для исполнения 152 ФЗ.
«На сайте осуществляется обработка файлов cookie, необходимых для работы сайта, а также для анализа использования сайта и улучшения предоставляемых сервисов с использованием метрической программы Яндекс.Метрика. Продолжая использовать сайт, вы даёте согласие с использованием данных технологий».
Политика конфиденциальности
|
|
|
Пятничные контейнеры
|
|||
|---|---|---|---|
|
#18+
Решил пособирать best practics Переписываю старый код на с++17 Код работает с контейнерами. Есть несколько векторов с объектами. В процессе обработки одного вектора, код может начать обработку другого вектора и в ней удалить элемент первого. Чтобы ничего плохого не случилось, у меня есть отдельные три вектора на добавление, удаление и перемещение объектов. И это немного неудобно, да и в коде выглядит криво. Поэтому вопрос, как лучше делать такой код: Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. в общем случае вектор сдвинется и итератор из верхнего кода станет невалидным, мы получим исключение ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 27.01.2018, 22:19 |
|
||
|
Пятничные контейнеры
|
|||
|---|---|---|---|
|
#18+
Код: plaintext 1. имелось ввиду Код: plaintext 1. если можно, исправьте в первом сообщении, а это потрите :) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 27.01.2018, 22:22 |
|
||
|
Пятничные контейнеры
|
|||
|---|---|---|---|
|
#18+
режим перфекциониста ON Код: plaintext 1. обычно пишут: Код: plaintext 1. еще лучше: Код: plaintext 1. короче: Код: plaintext 1. режим перфекциониста OFF ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 27.01.2018, 23:28 |
|
||
|
Пятничные контейнеры
|
|||
|---|---|---|---|
|
#18+
CEMb, возможно, нужен std::list. если не нужен произвольный доступ по индексу и нет задачи укладываться в кэш процессора. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 28.01.2018, 05:42 |
|
||
|
Пятничные контейнеры
|
|||
|---|---|---|---|
|
#18+
Cerebrumрежим перфекциониста ON Вот как раз перфекционисты пишут Код: plaintext 1. или, ещё лучше, используют using и договорённую нотацию, потому что взгляд человеком на auto-переменную для определения типа требует больше процессорного времени :) режим перфекциониста ON auto придуман для определения типа переменной в шаблонах, где просто так тип написать невозможно, а прокидывать его по параметрам или слишком дорого или тоже невозможно. Вот там auto нужен. В любых других местах использование auto это лень и моветон режим перфекциониста OFF да и просто самому неудобно читать ладно когда так: Код: plaintext 1. или так: Код: plaintext 1. ты сразу видишь, что там. Но вот когда так: Код: plaintext 1. где-то недавно попадался чудный код, типа Код: plaintext 1. человек ждал int на выходе, вычитал из него и проверял его на "меньше нуля", чтобы использовать, как индекс в массиве, а foo возвращало unsigned int. Ну и человек пошёл задавать вопросы на форум, почему у него всё ломается... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 28.01.2018, 09:00 |
|
||
|
Пятничные контейнеры
|
|||
|---|---|---|---|
|
#18+
alex_kи нет задачи укладываться в кэш процессорану вот есть такая задача :( т.е. нужно, чтобы по массиву обработчики бежали быстро ладно, буду думать :) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 28.01.2018, 09:01 |
|
||
|
Пятничные контейнеры
|
|||
|---|---|---|---|
|
#18+
CEMbт.е. нужно, чтобы по массиву обработчики бежали быстро Удаление из вектора это по определению не быстро )) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 28.01.2018, 12:33 |
|
||
|
Пятничные контейнеры
|
|||
|---|---|---|---|
|
#18+
Кстати ничего не мешает std::list хранить в непрерывном участке памяти (через соответствующий аллокатор) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 28.01.2018, 12:35 |
|
||
|
Пятничные контейнеры
|
|||
|---|---|---|---|
|
#18+
Anatoly MoskovskyУдаление из вектора это по определению не быстро )) Если не часто это делать, то не сильно напрягает. Но вот небезопасно - вот в этом у меня проблема. Я вообще думал, это довольно распространённое явление(add/del в массив во время итераций), и уже его как-то все побороли, один я отстал от жизни... о_о Ещё я эту проблему решал так: при удалении элементов, не удалял их а помечал, как удалённые. Удалял потом отдельным проходом. Тоже не айс. Anatoly MoskovskyКстати ничего не мешает std::list хранить в непрерывном участке памяти (через соответствующий аллокатор)Но там же надо следить за размеров выделенной памяти? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 28.01.2018, 19:47 |
|
||
|
Пятничные контейнеры
|
|||
|---|---|---|---|
|
#18+
CEMbAnatoly MoskovskyУдаление из вектора это по определению не быстро )) Если не часто это делать, то не сильно напрягает. Но вот небезопасно - вот в этом у меня проблема. "вниз цикл пустить" не предлагать? CEMbЕщё я эту проблему решал так: при удалении элементов, не удалял их а помечал, как удалённые. Удалял потом отдельным проходом. Тоже не айс.вполне норм, не вижу причин комплексовать ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 29.01.2018, 08:32 |
|
||
|
Пятничные контейнеры
|
|||
|---|---|---|---|
|
#18+
kealon(Ruslan)"вниз цикл пустить" не предлагать? это как? с end до begin? kealon(Ruslan)вполне норм, не вижу причин комплексовать не, не норм, это ж дополнительно ещё раз прогнать весь список. но второй мой вариант был ещё хуже: собирать всех удаленцев в один список (например, вектор указателей), а потом по нему удалять. тем временем, я с утра придумал такое простое, но корявое решение: 1. перед циклом запоминаем _Myend вектора 2. заводим индекс 3. после каждого прохода проверяем, изменился ли _Myend? Если да, то наш вектор перекочевал куда-то. Берём индекс из пункта 2 и считаем итератор заново: begin() + idx это всё отлично работает на добавлении в хвост . (я хотел сделать это ещё проще, перехватив _Orphan_All()) А вот с удалением всё несколько сложнее :) Вообще можно пойти в исходники вектора и посмотреть, как проверяется валидность итераторов (_Myfirst <= it <= _Mylast), но проблемы могут быть следующие: 1. insert, таким образом, мы можем на одном и том же элементе вызвать process() два раза 2. erase - тоже один элемент останется не обработанным т.е. даже если получать элементы по индексу из массива, а не по итератору, всё равно имеем проблемы. И в результате получается самый устойчивый вариант: хранить добавляемые, удаляемые, перемещаемые элементы в отдельных векторах и потом их отдельным ходом добавлять, удалять и перемещать. Но это выглядит громоздко: плюс 2-3 вектора. Может надо отказаться от итераций вообще? Придумать какой-нибудь механизм сообщений? В окнах же так, если я по событию нажатия в окне на одной кнопке, удаляю соседнюю, следующую по Z-order-у, ничего же не падает ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 29.01.2018, 13:00 |
|
||
|
Пятничные контейнеры
|
|||
|---|---|---|---|
|
#18+
CEMb, Работайте не с итераторами, а с индексами. Если если текущий элемент удален, то не инкрементировать индекс цикла. И все дела. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 29.01.2018, 14:05 |
|
||
|
Пятничные контейнеры
|
|||
|---|---|---|---|
|
#18+
Anatoly MoskovskyЕсли если текущий элемент удален, то не инкрементировать индекс цикла. И все дела. В том и проблема, что мы не знаем, удалён ли элемент. Так бы и проблем не было. В общем, надо подвести итог по этой теме C++ в данном случае не делает ничего лишнего и делает всё быстро, как и задумывалось. При этом можно просто добавлять контроль за итераторами, если надо, причём для разных ситуаций (к примеру, я буду только добавлять в хвост) можно оптимизировать этот контроль. я просто напишу простенький класс над вектором, с теми же методами, push, emplace, erase и т.д. который будет кешировать входящие значения, и добавлю метод refresh, который будет скидывать/применять временные вектора на постоянное хранилище. Снаружи всё будет выглядеть ровно как обычный вектор. Как вариант, можно было бы переопределить операторы ++, +, --, - для итератора и там проверять, что он не вышел за границы. Тут есть один момент, который упрощает ситуацию - функции, типа _Orphan_All зовутся напрямую из системной библиотеки у меня на Win7, msvcp120.dll, внутрь я сильно смотрел, но главное: они как-то умеют находить и сбрасывать все итераторы. Как только вектор переехал на новое место, или часть его сдвинулась - все итераторы, указывающие наружу, или те, под которыми память сдвинулась - сбрасываются. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 29.01.2018, 16:58 |
|
||
|
Пятничные контейнеры
|
|||
|---|---|---|---|
|
#18+
CEMb, std::reverse_iterator ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 29.01.2018, 20:50 |
|
||
|
Пятничные контейнеры
|
|||
|---|---|---|---|
|
#18+
kealon(Ruslan)std::reverse_iterator так он тоже не спасает от переноса вектора на новое место :( Btw, меня-таки припёрло, я собираюсь попробовать сделать абстрактный UI, из чего эта тема и выросла :) К примеру, идёт обработка сообщения, и обработчики "окон" порождают/убивают/переносят другие окна, нарушая консистентность. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 30.01.2018, 05:25 |
|
||
|
Пятничные контейнеры
|
|||
|---|---|---|---|
|
#18+
А вот ещё вопросы: - как сделать move одного вектора в хвост другого? Именно move, чтобы перемещаемый вектор стал нулевой длины? т.е. Код: plaintext 1. делает move по элементам, но сам вектор не трогает. - нужен ли такой перенос вектора? :) т.е. по идее это должно быть довольно быстро, по сравнению с переносом по элементам: 1. зарезервировать новую длину для dest 2. перенести source целиком по адресу хвоста dest но как оно на самом деле? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 30.01.2018, 08:09 |
|
||
|
Пятничные контейнеры
|
|||
|---|---|---|---|
|
#18+
CEMbkealon(Ruslan)std::reverse_iterator так он тоже не спасает от переноса вектора на новое место :( тынц CEMbBtw, меня-таки припёрло, я собираюсь попробовать сделать абстрактный UI, из чего эта тема и выросла :) К примеру, идёт обработка сообщения, и обработчики "окон" порождают/убивают/переносят другие окна, нарушая консистентность.В случае произвольного удаления, а не по ходу, итераторами пользоваться в любом случае нельзя. С другой стороны, если у вас нет доступа по проивольному индексу - зачем вам Vector? Если хотите нормально сделать, делайте сами класс под свои нужды, со своими плюшками. Костыли из STL для ширпотреба сделаны. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 30.01.2018, 09:10 |
|
||
|
Пятничные контейнеры
|
|||
|---|---|---|---|
|
#18+
kealon(Ruslan)В случае произвольного удаленияда, подразумевалось произвольное удаление. kealon(Ruslan)итераторами пользоваться в любом случае нельзя.вот у меня сомнения. Во-первых, я посмотрел внутрь вектора под дебагом. Он при фатальных изменениях вектора как-то знает, где у него все итераторы, и умеет их инвалидировать по надобности. Во-вторых, такая ситуация: три (прямых) итератора, указывают на 1, 3 и 5 элементы вектора. Делаем второму После этого первый валидный, а третий нет. Т.е. вектор, перенося хвост, заинвалидейтил только два итератора, оставив разумно первый в валидном состоянии. Т.е. по идее, я (код) могу понять, куда двинулся вектор или кусок вектора, и переместить за ним нужные итераторы. kealon(Ruslan)Если хотите нормально сделать, делайте сами класс под свои нужды, со своими плюшками.ага, это самый правильный вариант, получается. Я стал делать это, используя дополнительные векторы для удаляемых/добавляемых элементов. Но вот есть мысль, что можно было бы сделать одним вектором и с проверкой итераторов на валидность. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 30.01.2018, 11:06 |
|
||
|
Пятничные контейнеры
|
|||
|---|---|---|---|
|
#18+
CEMbА вот ещё вопросы: - как сделать move одного вектора в хвост другого? Именно move, чтобы перемещаемый вектор стал нулевой длины? т.е. Код: plaintext 1. делает move по элементам, но сам вектор не трогает. - нужен ли такой перенос вектора? :) т.е. по идее это должно быть довольно быстро, по сравнению с переносом по элементам: 1. зарезервировать новую длину для dest 2. перенести source целиком по адресу хвоста dest но как оно на самом деле? На самом деле применяется оператор std::move к каждому переносимому элементу. а будет это перемещение или копирование зависит от элемента. то что ты хочешь это что то типа Код: plaintext 1. Это в общем-то тоже самое что и Код: plaintext 1. 2. 3. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 30.01.2018, 11:56 |
|
||
|
Пятничные контейнеры
|
|||
|---|---|---|---|
|
#18+
YesSqlто что ты хочешь это что то типада, и я ничего такого не нашёл YesSqlЭто в общем-то тоже самое что инеее, там move делается на каждом элементе, идут итерации. А хочется просто одним куском перенести второй вектор в хвост первого. Это ничему не противоречит, так как там просто массив указателей, memcpy, очень быстро. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 30.01.2018, 12:06 |
|
||
|
Пятничные контейнеры
|
|||
|---|---|---|---|
|
#18+
YesSql, имелось ввиду Код: plaintext 1. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 30.01.2018, 12:07 |
|
||
|
Пятничные контейнеры
|
|||
|---|---|---|---|
|
#18+
CEMbYesSqlто что ты хочешь это что то типада, и я ничего такого не нашёл YesSqlЭто в общем-то тоже самое что инеее, там move делается на каждом элементе, идут итерации. А хочется просто одним куском перенести второй вектор в хвост первого. Это ничему не противоречит, так как там просто массив указателей, memcpy, очень быстро. одним куском нельзя. Как я уже сказал выше. зависит от элемента вектора - можно его переность или нельзя. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 30.01.2018, 12:12 |
|
||
|
Пятничные контейнеры
|
|||
|---|---|---|---|
|
#18+
YesSqlКак я уже сказал выше. зависит от элемента вектора - можно его переность или нельзя.а в каких случаях нельзя перенести? Если мы перенесём массив указателей, вроде бы ничего для элементов не поменяется? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 30.01.2018, 12:43 |
|
||
|
Пятничные контейнеры
|
|||
|---|---|---|---|
|
#18+
CEMbYesSqlКак я уже сказал выше. зависит от элемента вектора - можно его переность или нельзя.а в каких случаях нельзя перенести? Если мы перенесём массив указателей, вроде бы ничего для элементов не поменяется? Это твой очень частный случай. Врят-ли его внесут в стандарт. В общем случае только сам элемент знает как его можно перенести. И возможно ли это вообще ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 30.01.2018, 12:53 |
|
||
|
Пятничные контейнеры
|
|||
|---|---|---|---|
|
#18+
YesSqlЭто твой очень частный случай. Врят-ли его внесут в стандарт.не надо ничего вносить в стандарт :) YesSqlВ общем случае только сам элемент знает как его можно перенести.Не, я не про элементы, я про вектор, как контейнер. Итераторы - это указатели, и они лежат в памяти один за другим. А вот сами элементы могут лежать где угодно и как угодно и быть чем угодно. Но вектор это кусок непрерывной памяти с указателями. Как я понимаю, этот кусок памяти можно перенести безболезненно для любого типа элементов? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 30.01.2018, 13:57 |
|
||
|
|

start [/forum/topic.php?fid=57&msg=39592294&tid=2017984]: |
0ms |
get settings: |
8ms |
get forum list: |
12ms |
check forum access: |
4ms |
check topic access: |
4ms |
track hit: |
72ms |
get topic data: |
10ms |
get forum data: |
3ms |
get page messages: |
53ms |
get tp. blocked users: |
1ms |
| others: | 13ms |
| total: | 180ms |

| 0 / 0 |
