С ++ итераторы считаются вредными? - PullRequest
46 голосов
/ 08 мая 2009

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

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

  1. Являются ли итераторы плохими?
  2. Его замена действительно лучше?
  3. Будут ли разработчики C ++ подхватить его идеи?

Ответы [ 13 ]

40 голосов
/ 08 мая 2009

Сначала ответим на ваши вопросы:

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

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

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

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

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

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

4 голосов
/ 08 мая 2009

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

4 голосов
/ 08 мая 2009
  1. Большинство из нас просто использует их в так называемых идиомах, например в циклах for для итерации по std :: vector. Разработчик читает это и знает, что происходит. В нашей повседневной жизни программирование итераторы не являются хорошими или плохими, они просто «то, что выполняет работу».
  2. Возможно, да.
  3. Я так не думаю.
3 голосов
/ 26 января 2010
  1. Нет, они неплохие, на самом деле это очень умная идея. Однако они не идеальны, и в концепции итератора есть место для улучшений.

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

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

3 голосов
/ 08 мая 2009

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

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

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

3 голосов
/ 08 мая 2009

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

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

2 голосов
/ 12 мая 2009

Не пытается ли Андрей сделать какой-нибудь скрытый маркетинг для языка D (сейчас он работает с ним) ...?

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

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

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

или

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

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

2 голосов
/ 08 мая 2009

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

1 голос
/ 08 мая 2009

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

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

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

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

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

1 голос
/ 08 мая 2009

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

...