Итераторы C ++ считаются вредными?

Сегодня на конференции библиотеки Boost Андрей Александреску, автор книги «Современный дизайн C ++ и Loki C ++» библиотека, выступила с докладом под названием «Итераторы должны работать» (видео, слайды) о том, почему итераторы плохи, и у него было лучшее решение.

Я пытался прочитать слайды презентации, но ничего не смог извлечь из них.

  1. Итераторы - это плохо?
  2. Действительно ли его замена лучше?
  3. Подхватят ли его идеи разработчики C ++?

person Community    schedule 08.05.2009    source источник
comment
Наверное, должна быть вики сообщества.   -  person Brian    schedule 08.05.2009
comment
Слишком поздно, но я так не думаю: это обсуждение, связанное с программированием, которое определенно обменивается фактами, а не (только) мнениями.   -  person Konrad Rudolph    schedule 08.05.2009
comment
Интересно, почему у него нет функции find (), возвращающей что-то вроде boost :: optional   -  person    schedule 08.05.2009
comment
будут ли они размещать видео о бустконах?   -  person yesraaj    schedule 08.05.2009
comment
Вот интересная дискуссия об этом в usenet, в которой лично участвовал Алекс: groups.google.com/group/comp.lang.c ++. moderated / browse_thread /   -  person Johannes Schaub - litb    schedule 11.05.2009
comment
Ссылка на исходную статью, к сожалению, больше не действительна. Если у кого-то есть копия, было бы здорово, если бы они могли обновить ссылку!   -  person us2012    schedule 07.02.2013
comment
Нашел в Google, а также видеозапись его выступления. Я добавил ссылки на вопрос.   -  person Jo Liss    schedule 15.02.2016
comment
итераторы кажутся наиболее интуитивно понятным способом выбора всех записей в диапазоне в std :: map или подобных деревьях двоичного поиска. Интересно, это то, что базы данных используют внутри (кроме деревьев b *)   -  person Dmitry    schedule 01.04.2018


Ответы (13)


Во-первых, чтобы ответить на ваши вопросы:

  1. Нет. На самом деле, я утверждал в другом месте, что итераторы являются наиболее важными / фундаментальными концепция информатики когда-либо. Я (в отличие от Андрея) тоже считаю итераторы интуитивно понятными.
  2. Да, определенно, но это не должно вызывать удивления.
  3. Хм. Посмотрите на Boost.Range и C ++ 0x - не так ли?

Большой вклад Андрея здесь в том, чтобы просто сказать: полностью отказаться от концепции итераторов, рассматривать диапазоны не только как удобную оболочку, но и как основную конструкцию. Другие языки уже сделали это (многие концепции Андрея просто повторяют итераторы .NET LINQ или Python), но все они предлагают только диапазоны вывода. Андрей приводит аргументы в пользу разных типов диапазонов, как и в случае с обычными категориями итераторов.

В этом свете странно, что он начинает с насмешек над произвольностью этих категорий итераторов.

Я также думаю, что его примеры отключены, особенно его копирование файлов: да, вариант с итератором - это огромное улучшение по сравнению с кодом 1975 года. Он сокращает цикл со сложным условием прерывания до одного оператора. На самом деле он не согласен с синтаксисом. Что ж, извините: мы говорим здесь о C ++ - конечно синтаксис уродливый. И да, использование здесь диапазонов является улучшением, но только синтаксически.

Еще думаю, что у Андрея find реализация выключена. Что он действительно определяет, так это операцию DropUntil (именование сложно!) От LINQ. Операция find действительно должна возвращать либо один, либо ноль элементов (или итератор!). На мой взгляд, избегание итераторов здесь бесполезно, так как мы могли бы изменить значение напрямую, а не копировать его. Возврат одноэлементного диапазона здесь только добавляет накладные расходы без каких-либо преимуществ. Делать это по-Андреевски плохо, потому что тогда название метода просто неправильное и вводящее в заблуждение.

При этом я практически во всем согласен с Андреем. Итераторы, хотя и являются моей любимой концепцией из информатики, безусловно, представляют собой большую синтаксическую нагрузку, и многие диапазоны (особенно бесконечные генераторы) могут (и должны) быть удобно реализованы без них.

person Community    schedule 08.05.2009
comment
+1: Не уверен, что согласен со всем здесь, но читать очень интересно. Почти такой же провокационный, как сам великий Александреску :-) - person James Hopkin; 08.05.2009
comment
Вот почему я люблю программирование больше, чем математику. Есть мнения, и мы можем спорить. Гораздо интереснее этот путь. Также: итераторы потока решили проблему бесконечного диапазона, так что это возможно. Конечно, с дополнительной переменной-членом для конструктора по умолчанию, сигнализирующей о конце итератора, действительно возникают накладные расходы по сравнению с циклом while( true ), но насколько значительны эти накладные расходы? - person wilhelmtell; 09.04.2010
comment
@wilhelmtell: Вы правы, бесконечные диапазоны абсолютно выразимы с помощью итераторов, но синтаксис громоздок, поскольку мы должны определить какой-то произвольный «конечный» итератор, основная семантика которого просто должна быть неравной для всех других итераторов. Это довольно искусственно. Я не верю, что накладные расходы времени выполнения здесь значительны - возможно, их вообще нет (на самом деле не знаю). Мне просто странно вызывать операцию с итератором начала и конца, когда на самом деле конца нет. - person Konrad Rudolph; 09.04.2010
comment
Я думаю, что этот ответ полностью упускает суть. Boost :: range явно не то, что защищает Александр - он основан на итераторах. Что касается find - да, название не указано; но это потому, что здесь для ясности он отражает STL, который также вызывает эту функцию find. И если вы посмотрите на презентацию, то на самом деле демонстрируется сбой идиомы копирования файлов, когда член аудитории неправильно понимает код - чего не происходит с кодом C, который, несмотря на все, более понятен. - person Eamon Nerbonne; 30.12.2010
comment
@Eamon: (1) Я с уважением не согласен именно потому, что Boost.Range - это в значительной степени то, что защищает Андрей, хотя он этого не замечает. Реализация ниже довольно неинтересна (и да, итераторы делают отстой для некоторых из этих приложений). (2) find может отражать STL, но он немного - но фундаментально - отличается по своему поведению. Но я согласен, что вводить новое имя в презентации было бы неудобно. (3) Я первый, кто согласен с тем, что (а) C ++ «удобен для экспертов» и (б) его синтаксис - отстой. - Тем не менее, он маскирует сложность лучше, чем C, также в этом примере. - person Konrad Rudolph; 31.12.2010
comment
boost :: range имеет некоторые преимущества подхода, основанного на перечислении, но это не ничего особенного в том, что отстаивает Андрей. В частности, чтобы разобраться с ними, вам нужно понимать оба диапазона и итераторы (совсем не хорошо, если часть всей сути является упрощением). И они плохо моделируют обычное ленивое перечисление: как вы моделируете сетевой поток, поисковую систему «вычисление по мере необходимости», список (или строку) с завершающим нулем? Многие общие модели данных не имеют естественного конечного указателя, но действительно имеют естественное предложение if. - person Eamon Nerbonne; 01.01.2011
comment
Шутно утверждать, что он не замечает этого подхода, поскольку он явно упоминает возможность моделирования диапазонов поверх итераторов и отвергает это (правильно) как чрезмерно сложное, иногда неэффективное и ненужное. Вполне возможно иметь реализацию a диапазона, которая объединяет две итерации, но было бы ошибкой без надобности определять все диапазоны в терминах итераторов. Через что - 15 лет и больше? довольно ясно, что итераторы C ++ не так широко распространены, как перечислители, представленные в других языках (C #, ruby, python, F #, haskell ...). Скопируйте то, что работает ... - person Eamon Nerbonne; 01.01.2011
comment
@Eamon: «Было бы шуткой утверждать, что он не замечает такого подхода» - это было бы так, но я не заметил. Я согласен с тем, что B.R - не идеальное решение - на самом деле, однажды я попытался сгенерировать библиотеку диапазонов, аналогичную .NET Linq в C ++, и обнаружил, что это разочаровывает. Отсюда и мое заключительное замечание: «Я практически во всем согласен с Андреем. Итераторы, хотя и являются моей любимой концепцией из информатики, безусловно, представляют собой большую синтаксическую нагрузку, и многие диапазоны (особенно бесконечные генераторы) можно (и нужно) удобно реализовать без них ». (…) - person Konrad Rudolph; 01.01.2011
comment
@Eamon: (продолжение) ... Моя шляпа перед Б.Р. связана с практичностью. За исключением переписывания большей части стандартных библиотек C ++ и многих сторонних библиотек, диапазоны без итераторов не могут быть введены в C ++ без полной потери обратной совместимости, но основное дизайнерское решение C ++ заключалось в обеспечении обратной совместимости (для библиотек C , в таком случае). - Чем больше я читаю ваш первоначальный комментарий, тем больше у меня складывается впечатление, что вы на самом деле не прочитали мой ответ, кроме маркированного списка и абзацев о find и файле IO, потому что в оставшихся трех абзацах я подтверждаю аргументы Андрея - person Konrad Rudolph; 01.01.2011

Я согласен с ним в том, что итераторы в большинстве своем уступают диапазонам, и я не знаю, подберут ли «что-нибудь получше».

«Добро - враг лучшего», как обычно, играет здесь большую роль. Итераторы полезны и прочно укоренились, поэтому трудно понять, сможет ли что-то лучшее, например диапазоны, заменить их в разумные сроки.

person Community    schedule 08.05.2009

  1. Большинство из нас просто использует их в хорошо известных идиомах, например, в циклах for для итерации по std :: vector. Разработчик его читает и знает, что происходит. В нашей повседневной жизни кодирования итераторы не являются хорошими или плохими, они просто «то, что выполняет свою работу».
  2. Возможно - да.
  3. Я так не думаю.
person Community    schedule 08.05.2009

Андрей временами может быть немного провокационным. Итераторы - разумная концепция и довольно фундаментальная в том смысле, что и биты. Но так же, как большинство битов в C ++ не являются логическими значениями, а являются частью более крупных типов, с большинством итераторов следует обращаться на высоком уровне. Андрей прав в том, что подходящим уровнем для этого является объект диапазона. Но не все диапазоны правильно отображаются как диапазоны итератора, как показывает дозорный istream_iterator. Это просто хитрость для создания искусственного конечного итератора. Однако я не думаю, что его идеи будут подхвачены реализацией. C ++ 1x будет иметь такое же значение, как и C99.

person Community    schedule 08.05.2009

C ++ 0x уже делает первые шаги:

  • Ссылки rvalue решают некоторые проблемы с обработкой контейнеров как диапазонов
  • диапазоны были добавлены в основную библиотеку, включая концепции диапазонов

Переход к диапазонам без потери какой-либо функциональности итератора (подумайте обо всех комбинациях категорий итераторов, константности и rvalue-ness) является трудным, особенно если вы пытаетесь учитывать бесконечные и изменяемые диапазоны.

person Community    schedule 08.05.2009

  1. Нет, неплохие, на самом деле очень умная идея. Однако они не идеальны, и в концепции итератора есть возможности для улучшения.

  2. Он решает ряд реальных проблем с итераторами. Например, во многих случаях утомительно (также подвержено ошибкам) ​​запрашивать два отдельных объекта, итератора, из одного контейнера, а затем передавать их как еще два отдельных объекта в алгоритм. Почему бы не пропустить ни одного предмета? Даже std::pair<iterator, iterator> будет грубым диапазоном, которым легче манипулировать - один объект, а не два. Кроме того, неплохо было бы рассмотреть a range is an iterator. Собственно, Андрей и предлагает. Кстати, некоторые из этих проблем уже решены с помощью Boost . Диапазон.

  3. Я ожидал, что это произошло, но это будет не революция, а скорее эволюция.

person Community    schedule 25.01.2010

Я думаю, что мы должны использовать диапазоны рядом с итераторами, т.е. мы должны выбирать путь эволюции, а не путь революции.

person Community    schedule 08.05.2009

Разве Андрей не пытается провести скрытый маркетинг для языка D (в настоящее время он работает с ним) ...?

Андрей заявляет, что с контейнерами все в порядке, но итераторы уродливы, не интуитивно понятны, подвержены ошибкам и опасны, их сложно реализовать (ну, последнее кажется довольно верным ...) И что у нас есть в C ++ ... указатели ? Разве они не уродливы /.../ опасны? Но мы с радостью приняли их и живем с ними.

Какой из них писать более интуитивно:

for(auto i=foo.begin();i!=foo.end();++i)
    bar(*i);

or

for (auto r=foo.all(); !foo.empty(); foo.popFront())
        bar(r.front());

Концепцию итераторов можно дополнять диапазонами и другими идеями, но я думаю, что они нашли свое место и не подлежат замене.

person Community    schedule 12.05.2009
comment
Разве Андрей не пытается провести какой-то скрытый маркетинг для языка D. Меня интересовало то же самое. - person Unknown; 12.05.2009
comment
Он есть, и он также стоит за некоторыми конструкциями, которые стали намного более доработанными. Boost постоянно расширяется и переписывает себя в стиле STL времени компиляции, но он нарушает интерфейсы и вносит сложность, убивающую множеством ошибок. Мне все равно, C ++, D или C #, итератор или нет. Мне просто нужен поддерживаемый код, не вдаваясь в детали этого уровня, точно так же, как я не хочу вдаваться в подробности MPL (это самоубийство, машинный перевод должен делать то, что вам нужно, а не мозг, выбирающий синтаксис, чтобы понять его в смысле с обычным клавиатурным рефлексом :). Они пойдут'. - person rama-jka toti; 16.05.2009

  1. Иногда
  2. Наверное
  3. Маловероятно, по крайней мере, на много лет
person Community    schedule 08.05.2009
comment
Почти хайку, молодец двадцатого века, дадут нам еще? - person Binary Worrier; 08.05.2009

Как и любой API или функция, неправильное использование может создать множество проблем с идентификацией. Итераторы использовались во многих проектах, но всегда сохраняли необходимую заботу, требуемую в соответствии с их характеристиками. Его использованию должно предшествовать хорошее понимание их ограничений. Итераторы могут быть очень полезны при правильном использовании.
Эти вопросы связаны:
Есть ли способ проверить, действителен ли итератор?
Следует ли мне предпочесть итераторы над константами итераторами?

person Community    schedule 08.05.2009

Я не согласен и с Андреем, и с Конрадом, и со мной :-)

Самая фундаментальная концепция - это интерфейс, а не итератор, и это довольно очевидно в любой работе, которую кто-либо делает сегодня (которая связана с кросс-библиотекой, кросс-языками, кросс-компилятором, кросс-ОС, кросс-платформенностью, вы перекрестно называете Это :-)

Ни итератор, ни диапазон (кроме использования на уровне исходного кода) не предлагают ничего, кроме чистого и простого, ненавязчивого или навязчивого, не разделяемого или разделяемого, не уникального или уникального: указателя! Чистый указатель на типизированные данные просто универсален, и вы можете сделать данные изменяемыми или неизменяемыми и многое другое. Весь интерфейс - это просто еще один уровень косвенного обращения к нему, при этом он удобен для машин и компиляторов всех видов, а также гораздо безопаснее, поскольку итераторы и использование диапазона относятся к деталям реализации.

В этом смысле IEnumerable и IQueryable делают наполовину `` правильные вещи '' TM, но они явно уступают в своих концепциях итерации и многого другого по сравнению с тем, что вы можете делать с STL, сохраняя контроль и т. и, следовательно, лучшая, более чистая модель). Дело в том, что с интерфейсами вы можете построить любую абстракцию, которую хотите и удовлетворить, ну, вероятно, противоречивую, но по существу простую: оптимальное и нейтральное во время выполнения или компиляции представление данных и код (черт возьми, это важно для алгоритмов, компиляторов, виртуальных машин и тому подобного) .

Можно даже оптимизировать его для «динамических» / компонентных систем вплоть до встраивания «времени выполнения» (к черту HotSpot VM :-) .. В этом смысле прогресс до 1975 года минимален, о чем свидетельствует огромная рабочая нагрузка в индустрии взаимодействия (это повсюду посмотрите, в том числе этот сайт, использование проприетарных и открытых технологий и т. д., в идеализме информатики, ну, такого типа "работы" взаимодействия не должно существовать, если оно есть) ..

person Community    schedule 08.05.2009
comment
Дело в том, что вам нужен четко определенный интерфейс (или его набор). Итак, действительно вопрос: какой интерфейс использовать? Тот, который предлагают итераторы? Диапазоны? … - person Konrad Rudolph; 09.05.2009
comment
Полностью согласен ... imho, то, что никогда не будет зависеть от технологии или отдельной идеи, - это путь вперед, инструменты, ориентированные на предметную область и модель, будут иметь там такие же тяжелые времена. Кроме того, мир таков, что одно проприетарное решение применяется вместо другого для привязки к поставщику, особенно в отношении виртуальных машин и их собственных идей интеграции (доли рынка). Но все это по-прежнему поддерживает идею K&R как минимальную и полную, во многом подобно тому, как шаблоны и концепции в C ++ продвигаются вперед, или, действительно, метаданные среды выполнения помогают другому аспекту «изменения формы» / повторного использования. Протоколы просто сложно выполнять и соблюдать. - person rama-jka toti; 09.05.2009
comment
Кстати, что хуже всего, он делает хитрости, подобные Линусу, прямо в C ++, являясь движущейся целью для почти фундаментального изменения абстракции, которое значительно влияет на клиентский код (или до точки простоты поломки). Опять же, ядро ​​Linux находится в таком состоянии, что оно не подходит ни для чего, кроме ОС и простой сборки (что, я думаю, достаточно, но все еще негибкое для будущего). Не то чтобы другие ОС не копировали и не изобретали * nix заново, т.е. W6.0, особенно W7, но модульность возникает не только из-за разрыва зависимостей. [Кто-нибудь исправит дрянные ограничения HTML ASP.NET для этого сайта, ПОЖАЛУЙСТА] - person rama-jka toti; 09.05.2009
comment
В данном случае повторное использование выходит за рамки модуля / сборки и объектно-ориентированного подхода и применяется к протоколам и механизмам, которые фактически являются алгоритмами или дружественными алгоритму (CLR - нет; т.е. числовые значения). Последовательности представляют собой проблему для каждого протокола со сложными, непримитивными типами, черт возьми, даже простые массивы могут иметь аналогичные проблемы. LINQ не будет везде так очевиден с непрерывными попытками потоковой передачи, он такой же раздутый и тяжелый, как любой протокол высокого уровня. - person rama-jka toti; 09.05.2009
comment
Не думаю, что вы ответите на вопрос. Да, нам нужен интерфейс. Как это должно выглядеть? Итераторы определяют интерфейс. Так что сделайте диапазоны. Но интерфейса нет. - person jalf; 16.05.2009
comment
Конечно, ответа нет .. но то, что вы определенно хотите увидеть, - это изменение интерфейса в модели, а не в источнике. В нынешнем виде любое изменение просто нарушает код и идиомы. То, чем пользуются многие библиотеки; все, что я хочу, это изменить его, так как базовое оборудование может предпочесть что-то другое. Почему это должен быть конкретный интерфейс? Так кто-нибудь может прийти и сказать, что абстракция снова «устарела»? Это типично для C ++ и будет типичным для C ++, заново изобретающего себя, о чем идет речь. - person rama-jka toti; 16.05.2009
comment
Обратите внимание, что я не сторонник итератора, диапазона, IEnumerable или IQueryable ... мой аргумент - нейтралитет, и ни один из них не дает мне ни одного кросс-языкового, кросс-компилятора или чего-либо подобного. Это просто знамение времени: вы выбираете свое, кто-то другой выбирает другое, в зависимости от фазы луны. Я бы предпочел иметь возможность сказать, что мне все равно, итератор это или диапазон, но это может быть только я ... - person rama-jka toti; 16.05.2009
comment
@ rama-jkatoti Я помню печальный день в Haskell IRC (я только начинал с Haskell), и все они пытались впечатлить меня своими знаниями класса CS о монадах и прочем, в то время как я пытался понять, как работает их утверждение о компонуемости при отсутствии интерфейсов (групп функций). Они сошлись со мной в снобии, а все, что им нужно было сделать, это указать мне на курсы набора текста - духовный эквивалент интерфейсов на других языках (или черты характера для вас, русские ...). Теперь, несколько лет спустя, я делаю вывод: такие компонентные технологии, как COM, существуют только потому, что C ++ не определяет ABI. - person BitTickler; 08.08.2019
comment
@ rama-jkatoti (продолжение комментария): И если бы C ++ не был так игнорирует ABI (так что вы действительно можете создавать двоичные блоки кода), весь этот материал TMP, ориентированный на файл заголовка, никогда бы не вышел из-под контроля. Вместо этого, возможно, компилятор может поддерживать (общие) классы типов, и один из них может быть чем-то вроде Enumerable, и внезапно весь этот итератор и диапазон диапазонов станут не темой. - person BitTickler; 08.08.2019

Я думаю, что у разработчиков C ++ будут свои руки, чтобы обеспечить полную рабочую поддержку C ++ 0x без реализации новых нестандартных парадигм.

person Community    schedule 08.05.2009
comment
Разве диапазоны не являются стандартными для некоторых других языков? - person Unknown; 08.05.2009
comment
Ну и что? На других языках доступно множество вещей, которых нет и, вероятно, никогда не будет в C ++. - person ; 08.05.2009

Единственный аргумент, который я вижу в этой презентации, - это неспособность определять диапазоны, и предложение c ++ 0x «Диапазон для оператора», похоже, в какой-то степени устраняет эту проблему. возможно, это не должно быть аргументом в пользу того, что итераторы должны / не должны использоваться вообще, но более того, в каких ситуациях следует / не следует их использовать?

person Community    schedule 08.05.2009