Здравствуйте, McSeem2, Вы писали:
MS>Итераторы — это бездарная попытка использовать C++ не по назначению. Теоретически это прикольно, но на практике ничего кроме пожизненного рака головы не получается. Посмотрите на буст — это же просто помойка. Развитие C++ должно закончиться так же как Си и Фортрана. Любые попытки его развивать делают только хуже. В этом плане язык Си — более православный. Он стандартизирован, легок в имплементации и все хорошо. C++ — это монстр и кадавр, обеспокоенный желудочно.
Здравствуйте, LaptevVV, Вы писали:
LVV>Здравствуйте, McSeem2, Вы писали: LVV>>>Итератор — это объект, обеспечивающий последовательный доступ к элементам контейнера. LVV>>>Вот и все. MS>>А тогда что такое "итератор произвольного доступа"? А такой есть и даже свойство такое есть. Это оксиморон. LVV>Я таких иностранных слов не знаю...
Стыдись, ты ж преп!
LVV>Но В С++ многое сделано в угоду пресловутой обратной совместимости с С — это самая большая ошибка Страуструпа. LVV>Вот и итераторы сделаны по аналогии с указателем — "естественным итератором" для массивов. LVV>ИМХО — это дебилизм — обеспечение обратной совместимости. "Хотели — как лучше, а получилось — как всегда"(с)
Демагогия.
Совместимость с Си тут вообще ни при чем.
Произвольные скачки по массиву — это действительно естественный способ обращаться к его элементам, что в С++, что в Фортране.
Свойство массива как структуры данных такое.
А итератор произвольного доступа — это просто двунаправленный итератор с дополнительным свойством: время перемещения сразу на несколько элементов не зависит от расстояния, в отличие от линейной зависимости в общем случае. Т.е. чисто оптимизационная вещь. Если тебе на скорость наплевать — пиши алгоритмы в терминах двунаправленных итераторов, они будут работать и с массивами, и со списками.
Здравствуйте, jazzer, Вы писали:
J>А итератор произвольного доступа — это просто двунаправленный итератор с дополнительным свойством: время перемещения сразу на несколько элементов не зависит от расстояния, в отличие от линейной зависимости в общем случае. Т.е. чисто оптимизационная вещь. Если тебе на скорость наплевать — пиши алгоритмы в терминах двунаправленных итераторов, они будут работать и с массивами, и со списками.
Коллега на работе написал итератор. Есть некая сильно упакованная структура данных, представляющая набор сегментов полигона с кривыми. Все, что требуется — последовательное чтение, типа "дай мне следующий сегмент". Сегменты бывают разные — типа отрезок, квадратическкая курва или кубическая курва. Казалось бы — итератор для этого — то, что доктор прописал. Но получилось настолько все кучеряво и длинно, что разобраться в этом теперь нетривиально. Получилась ненужная усложнистика на ровном месте. На самом деле все гораздо хуже — есть набор этих полигонов, для них используется итератор более высокого уровня. А сверху еще есть layers, для них — еще более отдельный итератор. В результате приключился взрыв на макаронной фабрике в виде недоступного пониманию спагетти-кода. Всех программистов в радиусе офиса засыпало макаронами. Такие дела.
McSeem
Я жертва цепи несчастных случайностей. Как и все мы.
Здравствуйте, McSeem2, Вы писали:
MS>Здравствуйте, jazzer, Вы писали:
J>>А итератор произвольного доступа — это просто двунаправленный итератор с дополнительным свойством: время перемещения сразу на несколько элементов не зависит от расстояния, в отличие от линейной зависимости в общем случае. Т.е. чисто оптимизационная вещь. Если тебе на скорость наплевать — пиши алгоритмы в терминах двунаправленных итераторов, они будут работать и с массивами, и со списками.
MS>Коллега на работе написал итератор. Есть некая сильно упакованная структура данных, представляющая набор сегментов полигона с кривыми. Все, что требуется — последовательное чтение, типа "дай мне следующий сегмент". Сегменты бывают разные — типа отрезок, квадратическкая курва или кубическая курва. Казалось бы — итератор для этого — то, что доктор прописал. Но получилось настолько все кучеряво и длинно, что разобраться в этом теперь нетривиально. Получилась ненужная усложнистика на ровном месте. На самом деле все гораздо хуже — есть набор этих полигонов, для них используется итератор более высокого уровня. А сверху еще есть layers, для них — еще более отдельный итератор. В результате приключился взрыв на макаронной фабрике в виде недоступного пониманию спагетти-кода. Всех программистов в радиусе офиса засыпало макаронами. Такие дела.
Если честно, я мало что понял
Но вообще, Boost.Iterator сильно помогает сократить количество кода — достаточно просто пару функций реализовать (типа dereference), а все операторы она сама сделает.
Но если сами эти две функции получаются сильно кучерявыми — тады ой
Но вообще, конечно, имеет смысл в самих контейнерах дополнительно предусматривать всякие методы типа for_each (так же, как сейчас предоставляется sort) — они зачастую могут быть сделаны на порядок проще аналогичного кода на итераторах.
Здравствуйте, ononim, Вы писали:
ND>>Я понимаю, ЧТО такое итератор, я понимаю (но не использую пока на практике), что такое графы, очереди, двусвязные списки и т.д. и .п. Я не очень понимаю, в каких конкретно областях эти самые итераторы используются на практике? Вот я и спросил, в нажедже, что опытные люди просто приведут пример из жизни. O>Да пажалста. Я системщик. Обертки-итераторы вокруг FindFirstFile/FindNextFile, перечисление процессов, модулей, потоков etc — все это есть и применяется в нашем текущем проекте.
ND>>Лично я вижу единственное реальное преимущество — мы можем для одной структуры (списка, дерева, ассоциативного массива и т.д.) иметь несколько текущих позиций и перебирать объекты в этих контейнерных структурах независимо — ну, например, имеем один стек, но вершин у него несколько и живут они независимо O>Итератор это обобщенное понятие, придуманное для того чтобы обобщить методы последовательного доступа к элементам различных контейнеров и ничего более. O>Что во первых позволяет не за??ирать голову программиста особенностями потрохов различных контейнеров, во вторых позволяет использовать один и тот же обобщенный (читай — шаблонный) С++ код для работы с различными контейнерами. То бишь читай здесь — http://www.cppreference.com/wiki/stl/algorithm/start и обрати внимание что приведенным там алгоритмам пофиг элементы какого контейнера им скармливают.
Понятно.
FindFirst/FindNext использовал неоднократно (тоже системщик), хотя итератор пока к ним прикрутить как-то желания не возникало. Подумаю.
Лично я ничего против итераторов не имею — мне лишь интересно, насколько широко народ их реально использует (ну, то есть, процентное соотношение объема текста умной книжки по СРР, посвященного итераторам к проценту реального их использования в жизни).
Касаемо выгоды шаблонного С++ кода для работы с различными контейнерами — ну, ИМХО, я опять же сужу по практике. При условии, что итератор готовый библиотечный и мы сами его не пишем, остается проблема ресурсов, которые он сжирает за свое существование. По современным меркам — мелочь. Но вот я когда-о еще в институте писал всяике полезняшки на MSVC. Потом по работе пришлось что-то делать на Delphi. Когда было нужно, залезал в свой старый код, брал готовые отлаженные куски (ну там, со строками работа, с файловыми операциями и т.д.), менял {} на begin-end и экономил на этом кучу времени. А написал бы я красиво с шаблонами, итераторами и прочими оптимайзами — переносимость код бы точно потерял как в ту, так и в другую сторону. Но, повторюсь, наверняка есть и свои плюсы внешних классов-итераторов!
Здравствуйте, Vain, Вы писали:
V>Здравствуйте, rm822, Вы писали:
V>>>Вопросы новичков в STL воспринимаются уже как троллизм? однако. R>>Он нам предлагает сравнить STL c MFC-обрубками, которые тоже построены на итераторах, тока называются они там POSITION. V>Как минимум для итераторов дребуется отдельный класс, POSITION это не класс, т.е. у него нет методов. С этой позиции MFC проще, т.к. меньше сущностей.
Точно, в MFC POSITION — просто переменная, а не класс. А если вы возьмете Борландовский TList, то там еще проще.
Здравствуйте, jazzer, Вы писали:
J>Здравствуйте, McSeem2, Вы писали:
MS>>Здравствуйте, jazzer, Вы писали:
J>>>А итератор произвольного доступа — это просто двунаправленный итератор с дополнительным свойством: время перемещения сразу на несколько элементов не зависит от расстояния, в отличие от линейной зависимости в общем случае. Т.е. чисто оптимизационная вещь. Если тебе на скорость наплевать — пиши алгоритмы в терминах двунаправленных итераторов, они будут работать и с массивами, и со списками.
MS>>Коллега на работе написал итератор. Есть некая сильно упакованная структура данных, представляющая набор сегментов полигона с кривыми. Все, что требуется — последовательное чтение, типа "дай мне следующий сегмент". Сегменты бывают разные — типа отрезок, квадратическкая курва или кубическая курва. Казалось бы — итератор для этого — то, что доктор прописал. Но получилось настолько все кучеряво и длинно, что разобраться в этом теперь нетривиально. Получилась ненужная усложнистика на ровном месте. На самом деле все гораздо хуже — есть набор этих полигонов, для них используется итератор более высокого уровня. А сверху еще есть layers, для них — еще более отдельный итератор. В результате приключился взрыв на макаронной фабрике в виде недоступного пониманию спагетти-кода. Всех программистов в радиусе офиса засыпало макаронами. Такие дела.
J>Если честно, я мало что понял
J>Но вообще, Boost.Iterator сильно помогает сократить количество кода — достаточно просто пару функций реализовать (типа dereference), а все операторы она сама сделает. J>Но если сами эти две функции получаются сильно кучерявыми — тады ой
J>Но вообще, конечно, имеет смысл в самих контейнерах дополнительно предусматривать всякие методы типа for_each (так же, как сейчас предоставляется sort) — они зачастую могут быть сделаны на порядок проще аналогичного кода на итераторах.
Ну, вы же понимаете, что "она сама сделает" вовсе не означает сокращения количества кода, как Вы написали. Сократите в одном месте — удлините в другом Если мне надо пару десятков параметров массива информационного обмена по MIL-1553 запихать в список и потом находить в них нужный, это три-четыре строчки моего пользовательского кода. Микро- если не наносекунды машинного времени. Та же операция через крутую библиотеку с внешним иетратором уложится в 2 строки пользовательского кода. Но взамен, я получу 200 строк кода библиотечного, где будут сотни ненужных проверок, вызовов, подвызовов, создание монстрозных объектов в памяти и т.д. и т.п. Не дай бог, придется это дело потом трассировать, если что не так! Вот я и спрашиваю, скажем, Вас, где, в каких практических случаях у вас на практике была необходимость использования этих шаблонных чудо-конктейнеров с внешними итераторами? Можете ли вы, анализируя сейчас те случаи, что-либо сказать об их эффективности?
Здравствуйте, ND322, Вы писали:
J>>Но вообще, Boost.Iterator сильно помогает сократить количество кода — достаточно просто пару функций реализовать (типа dereference), а все операторы она сама сделает.
ND>Ну, вы же понимаете, что "она сама сделает" вовсе не означает сокращения количества кода, как Вы написали. Сократите в одном месте — удлините в другом Если мне надо пару десятков параметров массива информационного обмена по MIL-1553 запихать в список и потом находить в них нужный, это три-четыре строчки моего пользовательского кода. Микро- если не наносекунды машинного времени. Та же операция через крутую библиотеку с внешним иетратором уложится в 2 строки пользовательского кода. Но взамен, я получу 200 строк кода библиотечного, где будут сотни ненужных проверок, вызовов, подвызовов, создание монстрозных объектов в памяти и т.д. и т.п. Не дай бог, придется это дело потом трассировать, если что не так! Вот я и спрашиваю, скажем, Вас, где, в каких практических случаях у вас на практике была необходимость использования этих шаблонных чудо-конктейнеров с внешними итераторами? Можете ли вы, анализируя сейчас те случаи, что-либо сказать об их эффективности?
Мне заклинание "MIL-1553" ни о чем не говорит, сорри.
Тем не менее, вы знакомы с CRTP?
Там нулевой оверхед, и Boost.Iterator сделана именно через него.
Так что очень интересно, где вы там нашли монструозные объекты и прочая
Насчет практических случаев — да, использовал многажды, никаких нареканий к эффективности, ибо CRTP.
Здравствуйте, Vain, Вы писали:
V>Так и итераторов будет два, если функцию find обернуть — придётся всегда пару итераторов возвращать, тогда как range уже какбе пара итераторов.
Здравствуйте, morm, Вы писали:
V>>Так и итераторов будет два, если функцию find обернуть — придётся всегда пару итераторов возвращать, тогда как range уже какбе пара итераторов. M>чего й то???
А как ты итератор на валидность проверишь?
[In theory there is no difference between theory and practice. In
practice there is.]
[Даю очевидные ответы на риторические вопросы]
Здравствуйте, ND322, Вы писали:
V>>>>Вопросы новичков в STL воспринимаются уже как троллизм? однако. R>>>Он нам предлагает сравнить STL c MFC-обрубками, которые тоже построены на итераторах, тока называются они там POSITION. V>>Как минимум для итераторов дребуется отдельный класс, POSITION это не класс, т.е. у него нет методов. С этой позиции MFC проще, т.к. меньше сущностей. ND>Точно, в MFC POSITION — просто переменная, а не класс.
typedef
[In theory there is no difference between theory and practice. In
practice there is.]
[Даю очевидные ответы на риторические вопросы]
Здравствуйте, jazzer, Вы писали:
J>Мне заклинание "MIL-1553" ни о чем не говорит, сорри. J>Тем не менее, вы знакомы с CRTP? J>Там нулевой оверхед, и Boost.Iterator сделана именно через него. J>Так что очень интересно, где вы там нашли монструозные объекты и прочая
в общем все правильно.
только если я правильно понял McSeem, там надо было путешествовать по различным коллекциям.
то есть итератор должен быть абстрактным -> оверхед виртуального вызова и управления памятью или ручная реализация через свитч.
J>Насчет практических случаев — да, использовал многажды, никаких нареканий к эффективности, ибо CRTP.
ND322 wrote:
> Умные книжки много пишут о прелестях итераторов для различных > контейнеров данных. Обычно приводятся примеры самостоятельных шаблонных > классов, осуществляющих перебор элементов собственно контейнерного > класса.
По факту итераторы -- говно.
Но когда говорят о их прелестях, то имеют в виду, что они позволяют
алготирмам, которые обрабатывают данные, абстрагироваться от
структуры тех данных, которые они обрабатывают. В этом их "прелесть"
с точки зрения дизайнеров STL.
ND322 wrote:
> готовый библиотечный и мы сами его не пишем, остается проблема ресурсов, > которые он сжирает за свое существование. По современным меркам — > мелочь. Но вот я когда-о еще в институте писал всяике полезняшки на
В 80% случаем, а может и в 90, итератор в реализации -- это лиш
прикрытый фиговым листком указатель. Так что никакой накладухи там
нет.
Просто итератор, выделенный как абстракция, позволяет делать их
разными, в том числе и тебе самому.
jazzer wrote:
> Произвольные скачки по массиву — это действительно естественный способ > обращаться к его элементам, что в С++, что в Фортране. > Свойство массива как структуры данных такое.
Вот кстати да. Почему бы не сделать было вместо итераторов
заклад на 3 функции :
-- size()
-- T& operator [] (unsigned n)
-- const T& operator [] (unsigned n) const
Здравствуйте, ND322, Вы писали:
ND>Умные книжки много пишут о прелестях итераторов для различных контейнеров данных. Обычно приводятся примеры самостоятельных шаблонных классов, осуществляющих перебор элементов собственно контейнерного класса. Вот снова попалось в литературе, решил спросить мнение гуру. Где и как на практике используется эта крутизна? В чем преимущество перед обыкновенным CList\TList, который перебирает сои элементы сам без всяких сложных конструкций. Лично мне на практике всегда хватало его возможностей. Чего я не понимаю в этой жизни? Где используются эти пресловутые классы-итераторы?
Кстати, интересный вопрос. Давайте сравним MFC CList с POSITION и std:list с его итераторами.
Пользуюсь и тем и другим, но как ни странно, больше нравится CList. Даже сделал с MFC'шных классов кроссплатформенную реализацию.
Итератор — это отдельная сущность, близкая к указателям, но обладающая своими методами. Итераторы, в отличие от указателей, могут быть устроены весьма нетривиально.
POSITION — это всего лишь 4-байтовое значение, с которым НИЧЕГО НЕЛЬЗЯ СДЕЛАТЬ, не имея собственно объекта-коллекции. POSITION идеологически ближе к индексу массива.
Лично мне немного понятнее, когда я вижу в коде 'arr[i]', чем когда '*ptr'; хотя с точки зрения производительности указатели будут быстрее.
Итераторы УНИВЕРСАЛЬНЕЕ, но НЕ НАГЛЯДНЕЕ... В том смысле, что запись с участием объекта-коллекции лишний раз подчеркивает, ЧТО ИМЕННО мы делаем в этой строчке. Не просто берем из памяти какое-то значение, а берем конкретно i-тое значение из массива с конкретным именем.
Итератор можно передать куда-нибудь в функцию сам по себе, без контейнера, и делать с ним там что угодно. Впрочем, не совсем что угодно... для собственно ИТЕРАЦИИ нужен еще один итератор — на конец коллекции.
В случае с MFC CList требуется передавать и итератор, и ссылку на саму коллекцию.
Итераторы синтаксически подобны указателям, т.е. используются переопределенные операторы ++, --, *. MFC использует методы GetAt(), GetNext(), GetPrev(). Вариант с итераторами, опять-таки, универсальнее... Теоретически, можно заменить итератор на обычный указатель, и все должно работать.
Но мне в принципе не нравится переопределение операторов. Я вижу 'p++', и как я угадаю, будет ли это простая команда inc, или вызов целого метода? Т.е. вариант с методами GetAt() и т.д. лично мне нравится больше — именно тем, что там все записывается ЯВНО.
Основной аргумент в пользу итераторов из предложенных выше — итераторы универсальны, т.е. можно одними и теми же алгоритмами обрабатывать и массивы, и списки, и хз что еще. Однако у меня возникает вопрос практической необходимости такой универсальности. В моих программах, как правило, любая коллелкция — это часть какого-либо класса, и она используется там исключительно для конкретных нужд класса. Методы класса реализуют конкретные алгоритмы, связанные с конкретной предметной областью, и как правило очень сильно заточены под логику этой предметной области. Иными словами, алгоритмы обработки конкретной коллекции совершенно бесполезны и бессмысленны для другой коллекции в другом классе.
С точки зрения замены типов коллекций. Часто вижу такой аргумент: если вдруг захочется заменить vector на list или наоборот, то все что нужно сделать — просто заменить тип в объявлении объекта-коллекции.
Народ, вот это мне как минимум непонятно... Выбор типа для коллекции — фундаментальная вещь, которая должна делаться один раз в самом начале разработки того или иного класса. Мне и в бреду не придет мысль менять list на vector, если я знаю КАК ИМЕННО я работаю с коллекцией, для каких целей я ее вводил в программ и для чего она там используется...
И еще. Для работы с GUI часто требуется привязать какие-то "итераторы" к элементам контролов (методы типа SetItemData()/GetItemData()). POSITION — это гарантированно 4-байтовое значение, которое легко привязывается простым приведением типов. С итераторами такой номер не прокатит, это класс, который разумеется нельзя приводить к DWORD, void*, LPARAM и т.д.
На этот вопрос, кстати, мне так толком никто и не ответил.
Вероятно, истина как всегда где-то рядом, может быть посередине
V>>>Так и итераторов будет два, если функцию find обернуть — придётся всегда пару итераторов возвращать, тогда как range уже какбе пара итераторов. M>>чего й то??? V>А как ты итератор на валидность проверишь?
Проверять в программе надо только входные данные, ибо они не под вашим контролем. Итератор должен _быть_ валиден, ибо код который вы пишете под вашим контролем. Или нет?
Как много веселых ребят, и все делают велосипед...
XC>Лично мне немного понятнее, когда я вижу в коде 'arr[i]', чем когда '*ptr'; хотя с точки зрения производительности указатели будут быстрее. XC>Итераторы УНИВЕРСАЛЬНЕЕ, но НЕ НАГЛЯДНЕЕ... В том смысле, что запись с участием объекта-коллекции лишний раз подчеркивает, ЧТО ИМЕННО мы делаем в этой строчке. Не просто берем из памяти какое-то значение, а берем конкретно i-тое значение из массива с конкретным именем.
А вот и нифиге. Мне индексы совершенно не наглядны. Я даже если пишу for(...) по массиву заданному голым указателем — использую арифметику указателей, а не индексы. Так что это просто дело привычки — для человека который годами в паскале/бейсике писал for i .... индекс будет конечно нагляднее, а вот для человека "со стороны" — совсем даже не факт.
Как много веселых ребят, и все делают велосипед...
Здравствуйте, MasterZiv, Вы писали:
MZ>jazzer wrote:
>> Произвольные скачки по массиву — это действительно естественный способ >> обращаться к его элементам, что в С++, что в Фортране. >> Свойство массива как структуры данных такое.
MZ>Вот кстати да. Почему бы не сделать было вместо итераторов MZ>заклад на 3 функции : MZ>-- size() MZ>-- T& operator [] (unsigned n) MZ>-- const T& operator [] (unsigned n) const
MZ>Ничем не хуже.
А теперь придумайте такой же "лисопед" для list, set, map... При этом имейте в виду, что кто-то возможно захочет итерацию по коллекции в цикле...
Здравствуйте, jazzer, Вы писали:
MS>>>А тогда что такое "итератор произвольного доступа"? А такой есть и даже свойство такое есть. Это оксиморон. LVV>>Я таких иностранных слов не знаю... J>Стыдись, ты ж преп!
LVV>>Но В С++ многое сделано в угоду пресловутой обратной совместимости с С — это самая большая ошибка Страуструпа. LVV>>Вот и итераторы сделаны по аналогии с указателем — "естественным итератором" для массивов. LVV>>ИМХО — это дебилизм — обеспечение обратной совместимости. "Хотели — как лучше, а получилось — как всегда"(с)
J>Демагогия. J>Совместимость с Си тут вообще ни при чем.
Еще как причем... Вот нельзя было бы в С арифметические операции с указателями делать, и не стали бы реализовывать "итератор произвольного доступа" — для совместимости с указателем. J>Произвольные скачки по массиву — это действительно естественный способ обращаться к его элементам, что в С++, что в Фортране. J>Свойство массива как структуры данных такое.
Ага. Только обеспечивается оно индексом, а не итератором. J>А итератор произвольного доступа — это просто двунаправленный итератор с дополнительным свойством: время перемещения сразу на несколько элементов не зависит от расстояния, в отличие от линейной зависимости в общем случае. Т.е. чисто оптимизационная вещь. Если тебе на скорость наплевать — пиши алгоритмы в терминах двунаправленных итераторов, они будут работать и с массивами, и со списками.
Это от задачи зависит.
Хочешь быть счастливым — будь им!
Без булдырабыз!!!