2010-05-13 6 views
29

Я разработчик Java, пытающийся изучить C++. Я много раз читал в Интернете (включая Stack Overflow), что STL - это лучшая коллекция, которую вы можете получить в любом языке. (Извините, у меня нет ссылок)Что такого хорошего в STL?

Однако после изучения некоторых STL, я действительно не понимаю, что делает STL таким особенным. Не могли бы вы пролить свет на то, что отличает STL от библиотек коллекций других языков и делает его лучшей библиотекой коллекций?

+15

STL не является «специальным», он является частью стандарта C++. 'boost' является особенным. –

+11

О да, STL ** очень ** особенный. Посмотрите на все другие стандартные библиотеки, и вы увидите, насколько особенным является STL. – wilhelmtell

+3

@ Kirill: Строго говоря, STL полностью двусмысленна. C++ не имеет понятия STL, только Standard Library. STL может ссылаться на части шаблона стандартной библиотеки или на оригинальную стандартную библиотеку шаблонов, опубликованную SGI, или даже на что-то еще. – GManNickG

ответ

23

Что такого хорошего в STL?

STL отлично подходит для того, чтобы он был задуман очень рано и все же успешно применял парадигму обобщенного программирования C++ довольно эффективно.

Она отделена эффективно структуры данных: vector, map, ... и алгоритмы для работы на них copy, transform, ... пользуясь шаблонами, чтобы сделать это.

Это аккуратно развязанные проблемы и предоставленные общие контейнеры с крючками настройки (Comparator и Allocator параметров шаблона).

Результат очень элегантный (принцип DRY) и очень эффективен благодаря оптимизации компилятора, так что ручные алгоритмы для данного контейнера вряд ли будут лучше.

Это также означает, что он легко расширяется: вы можете создать свой собственный контейнер с помощью интерфейса, который вы хотите, до тех пор, пока он предоставляет STL-совместимые итераторы, вы сможете использовать с ним алгоритмы STL!

И благодаря использованию признаков вы можете применять алгоритмы на C-массиве с помощью простых указателей! Поговорите о обратной совместимости!

Однако, это может (возможно) было бы лучше ...

Что не так велика о STL?

Это действительно бесит меня, что всегда нужно использовать итераторы, я действительно стоять будучи в состоянии написать: std::foreach(myVector, [](int x) { return x+1;}); потому, что лицо это, в большинстве случаев вы хотите перебрать весь контейнер. ..

Но что еще хуже, что из-за этого:

set<int> mySet = /**/; 

set<int>::const_iterator it = std::find(mySet.begin(), mySet.end(), 1005); // [1] 
set<int>::const_iterator it = mySet.find(1005); // [2] 

[1] и [2] осуществляется совершенно по-разному, что приводит к [1] имея O (N) сложность, а [2] имеет O (журнал п) сложность! Здесь проблема в том, что итераторы слишком абстрактны.

Я не имею в виду, что итераторы недостойны, я имею в виду, что предоставление интерфейса исключительно с точки зрения итераторов было плохим выбором.

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

Объединение взгляды и концепцию проверки идеи будет, я думаю, производить гораздо более удобный интерфейс для алгоритмов STL (и решить это find, lower_bound, upper_bound, equal_range выпуск).

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

+2

По крайней мере, в C++ 0x у вас будет доступ для каждого цикла для итераторов! –

+0

Большинство ваших проблем - проблемы с языком C++, а не с самим STL. +1 хотя - я согласен с схватками. –

+2

Оба представления и проверки понятий доступны в C++ (хотя вам, возможно, придется работать, чтобы их получить). Представления схожи с контейнерами-адаптерами (с делегированным хранилищем), а Boost.Concept - живой и пинающий. Проблема у меня с итераторами, а не с C++ :) –

3

Ну, это что-то вроде смелого заявления ... возможно, в C++ 0x, когда он наконец получает хеш-карту (в виде std :: unordered_map), он может сделать это требование, но в своем текущем состояние, ну, я этого не покупаю.

Я могу сказать вам, однако, некоторые интересные вещи об этом, а именно, что он использует шаблоны, а не наследование, чтобы достичь своего уровня гибкости и общности. Это имеет как преимущества, так и недостатки; недостатком является то, что много кода дублируется компилятором, и любой тип динамического набора времени выполнения очень трудно достичь; однако ключевым преимуществом является то, что он невероятно быстрый. Поскольку каждая специализированная специализация действительно представляет собой отдельный отдельный класс, сгенерированный компилятором, он может быть оптимизирован для этого класса. Кроме того, многие алгоритмы STL, которые работают на контейнерах STL, имеют общие определения, но имеют специализации для особых случаев, которые приводят к невероятно хорошей производительности.

+1

Re: дублирование кода, некоторые линкеры могут конденсировать идентичные функции в одну копию (например, MS/Gy) - поэтому любой код, который не встроен, не будет дублироваться. И если вы укажете опционы для оптимизации размера (не скорости), функции будут только встроены, когда это действительно приведет к уменьшению кода. Также не уверен, что вы подразумеваете под «динамическим набором времени выполнения», которого трудно достичь - просто используйте контейнер указателей (или интеллектуальных указателей, чтобы упростить очистку). –

26

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

В частности, стандартная библиотека C++ использует обобщенного программирования парадигмы, а не объектно-ориентированной парадигмы, что является общим в языках, как Java и C#. То есть, у вас есть «общее» определение того, что такое iterator должно быть, а затем вы можете реализовать функцию for_each или sort или max_element, который принимает любой класса, который реализует iterator шаблона, фактически не имея наследовать от некоторой основы " Iterator "или что угодно.

+2

Фактически подход «статической утиной печати» применяется также к контейнерам компилятором C#. 'foreach' может перечислить любой объект с методом GetEnumerator, а инициализаторы коллекций работают над любым объектом' IEnumerable', который * также имеет метод 'Add', поэтому он просто находит имена методов и подписи, независимо от типа они определены в, как и шаблоны C++. –

+2

Ха! Я вижу «interator» - мне жаль, что у меня не было 1 доллара за каждый раз, когда я набрал это. Мышечная память работает против нас :( – msandiford

+0

@spong: Отредактировано это для вас :) – missingfaktor

13

Контейнеры STL хороши, но они не сильно отличаются от других языков программирования. Что делает контейнеры STL полезными, так это то, что они прекрасно сочетаются с алгоритмами. Гибкость, обеспечиваемая стандартными алгоритмами, не имеет себе равных в других языках программирования.

Без алгоритмов контейнеры именно это. Контейнеры. Ничего особенного.

Теперь, если вы говорите о библиотеках контейнеров только для C++, маловероятно, что вы найдете библиотеки, также используемые и протестированные как те, которые предоставляются STL, если ничего другого, поскольку они являются стандартными.

+2

Не говоря уже о том, что на любом достойном компиляторе STL супер оптимизирован. – Anthony

+0

@Duracell: Любая другая библиотека может быть оптимизирована аналогично, и на самом деле ее можно даже оптимизировать, если вы захотите отказаться от некоторых гарантий, которые STL делает в своих коллекциях. –

+0

Да и нет. Большинство других библиотек в значительной степени зависят от косвенности, интерфейсов, наследования и таких исполняемых функций. STL может быть оптимизирован тривиально, если у вас есть встроенный компилятор, потому что вся абстракция оценивается во время компиляции. – jalf

8

Это не прямой ответ, но, как вы поступаете с Java, я хотел бы указать на это. По сравнению с эквивалентами Java, STL действительно быстро.

Я нашел this page, показывая некоторые сравнения производительности. Как правило, люди Java очень трогательны, когда речь заходит о переговорах по производительности, и заявляют, что все виды достижений происходят все время. Однако аналогичные успехи происходят и в компиляторах C/C++.

+2

Это отличная точка - можете ли вы ссылаться на любые данные по этому вопросу? – JBRWilkinson

20

Что мне нравится в STL, насколько он прочен. Его легко расширить.Некоторые жалуются, что он маленький, не хватает многих общих алгоритмов или итераторов. Но это именно то, когда вы видите, как легко добавлять недостающие компоненты, которые вам нужны. Мало того, но маленькое красиво: у вас есть около 60 алгоритмов, несколько контейнеров и несколько итераторов; но функциональность находится в порядке продукта из них. Интерфейсы контейнеров остаются небольшими и простыми.

Потому что это модно писать небольшие, простые, модульные алгоритмы, легче обнаружить ошибки и дыры в ваших компонентах. Тем не менее, в то же время, так же просто, как и алгоритмы и итераторы, они необычайно надежны: ваши алгоритмы будут работать со многими существующими и еще не написанными итераторами, а ваши итераторы работают со многими существующими и все-таки- написанные алгоритмы.

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

Niklaus Wirth сказал, что программа представляет собой алгоритмы и структуры данных. Именно об этом и говорит STL. Если Ruby и Python являются супергероями строк, то C++ и STL являются супергероем с алгоритмами и контейнерами.

+1

+1 за хорошо написанный и информативный ответ – Robb

+3

На самом деле, я думаю, вы обнаружите, что это Вирт, а не Кнут - это название одной из его книг (вирт). – 2010-05-13 09:38:34

+1

@ Нил спасибо, я стою исправлено. http://en.wikipedia.org/wiki/Algorithms_%2B_Data_Structures_%3D_Programs – wilhelmtell

2

Уникальных, потому что

  • фокусируется на основных алгоритмах вместо предоставления готовых к использованию решений для конкретных прикладных задач.
  • использует уникальные возможности C++ для реализации этих алгоритмов.

Как за то, что лучше ... Существует причина, почему такой же подход не был (и, вероятно, не будет) никогда не следуют какой-либо другой язык, в том числе прямых потомков, как Д.

+3

_ «Существует причина, по которой тот же подход не был (и, вероятно, не будет) когда-либо сопровождаться каким-либо другим языком, включая прямых потомков, таких как D ,»_ - Не могли бы вы объяснить эти причины? – missingfaktor

+0

Да, пожалуйста .... –

+1

Потому что дизайнеры D знают лучше, чем эмулировать концепции OO с помощью шаблонов? (Легче узнать, что, черт возьми, идет не так, если вы сортируете функции требует «RandomAccessIterator' вместо' T') – KitsuneYMG

2

Стандарт Подход библиотеки C++ к коллекциям через итераторы в последнее время вызвал некоторую конструктивную критику. Андрей Александреску, известный эксперт по C++, недавно начал работу над новой версией языка D и describes his experiences designing collections support for it in this article.

Лично я считаю, что разочарование в том, что эта прекрасная работа внедряется в еще один язык программирования, который очень сильно перекрывает существующие языки, и я сказал ему об этом! :) Я бы хотел, чтобы кто-то из его специалистов переложил руку на создание библиотеки коллекций для так называемых «современных языков», которые уже широко используются, Java и C#, которые обладают всеми возможностями, которые, по его мнению, должны быть мирового класса: понятие диапазона с непрерывным повторением уже вездесуще, но как насчет обратного итерации эффективным образом? Что относительно изменчивых коллекций? Как насчет интегрирования всего этого с Linq? и т. д.

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

+1

, что «неуклюжий» способ позволяет сделать алгоритмы, работающие над сборками C++, более универсальными, поэтому они также работают над разделами коллекций, а не только целыми коллекциями. – smerlin

+1

Да, это неуклюжая, но мощная нотация. Я думаю, что Alexandrescu немного переборщил, полностью заменив итераторы диапазонами, но он явно что-то понял. В большинстве (но не во всех) случаях итераторы дают нам синтаксис, где слишком сложно создавать операции. – jalf

+0

@smerlin - рассмотрим класс, который реализует концепцию диапазона, делегируя другой диапазон, из которого он вырезает субдиапазон. например с учетом диапазона 'r' выражение' slice (r, 3, 4) 'возвращает объект, который, как представляется, содержит следующие элементы:' r [3], r [4], r [5], r [6 ] '. Итак, 'slice (r, 3, 4) [2] =" hi ";' будет эквивалентен 'r [5] =" hi ";' поэтому диапазоны поддерживают разделы разделов очень элегантно - больше, чем итераторы. –

13

STL прекрасно работает со встроенными типами. A std::array<int, 5> - это то, что - массив из 5 int s, который потребляет 20 байт на 32-битной платформе.

java.util.Arrays.asList(1, 2, 3, 4, 5), с другой стороны, возвращает ссылку на объект, содержащий ссылку на массив, содержащий ссылки на объекты Integer, содержащие int s.Да, это 3 уровня косвенности, и я не посмею предсказать, сколько байтов потребляет;)

+2

«Я не смею предсказать, сколько байтов потребляет» - вы не можете предсказать сколько байтов оно потребляет, потому что, например, вы не знаете, будет ли JVM использовать оптимизацию с небольшим целым при боксировании 'int'. Последний уровень косвенности может создать 5 объектов Integer или использовать 5 статических целых чисел объекты, которые всегда существуют. –

+2

@Steve «вы не можете предсказать, сколько байтов он потребляет» -> Я думаю, именно поэтому я не решался ;-) – fredoverflow

+0

'std :: array' - это« STL »сейчас? Ты просто растягиваешь его! –

7

Имейте в виду, что СТЛ на самом деле довольно стар, так и другие, новые библиотеки могут имеют определенные преимущества. Учитывая возраст, его популярность является свидетельством того, насколько хорош оригинальный дизайн.

Существует четыре основных причины, по которым я бы сказал, что STL (все еще) удивительная:

Скорости STL использует шаблоны C++, что означает, что компилятор генерирует код, который специально разработанный для использования вами библиотека. Например, карта автоматически генерирует новый класс для реализации коллекции карт типа «ключ» для типа «значение». Накладные расходы во время выполнения отсутствуют, когда библиотека пытается определить, как эффективно хранить «ключ» и «значение» - это делается во время компиляции. Благодаря элегантному дизайну некоторые операции над некоторыми типами будут скомпилированы до отдельных инструкций по сборке (например, итератор с добавлением целых чисел).

Эффективность Классы коллекции есть понятие «распределители», которые вы можете предоставить самостоятельно или использовать библиотеку, при условии, те, которые выделяют только достаточно места для хранения данных. Никаких отступов и потерь нет. Там, где встроенный тип может быть сохранен более эффективно, существуют специализации для оптимального управления этими случаями, например. вектор bool обрабатывается как битполе.

Exensibility Вы можете использовать контейнеры (классы сбора), алгоритмы и функции, предусмотренные в STL на любого типа, который подходит. Если ваш тип можно сравнить, вы можете поместить его в контейнер. Если он попадает в контейнер, его можно сортировать, искать, сравнивать. Если вы предоставляете функцию, как 'BOOL сказуемого (MyType)', он может быть отфильтрован и т.д.

Elegance Другие библиотеки/рамки должны реализовать Sort()/Find()/Reverse() методы на каждый тип коллекции. STL реализует их как отдельные алгоритмы, которые принимают итераторы любой коллекции, которую вы используете, и слепо следуете этой коллекции. Алгоритмы не заботятся о том, используете ли вы Vector, List, Deque, Stack, Bag, Map - они просто работают.

+1

Скорость: Шаблоны убивают скорость компиляции, а поиск в виртуальном указателе не принимает _that_ long. Это не 1970 год. Эффективность: сначала вектор - это мерзость, которая должна умереть. Активаторы не об эффективности, а о том, как создается и удаляется новый 'T'. Расширяемость: Это не уникально для STL. Черт, я пишу алгоритмы в java, которые принимают 'Iterator и/или' Predicate '. – KitsuneYMG

+2

Elegance: Опять же, это не уникально для STL. Любой общий язык программирования делает то же самое. Языки OO (например, java) предоставляют тип List, который определяет функцию сортировки. Он не говорит, что функция не может вызвать общий алгоритм сортировки. На самом деле у java List нет функции 'sort' member, они сортируются по статическому методу' Collections.sort'. – KitsuneYMG

+3

@ kts: Большинство разработчиков на C++ не очень заботятся о скорости компиляции; скорее; мы заботимся о скорости выполнения. Кроме того, шаблоны выполняются только медленно, если вы используете crappy-компилятор - у любого разумно недавнего компилятора нет проблем с ними. Будет ли это медленнее C во время сборки? Вероятно. Это не означает, что функция должна быть удалена. –

0

Главное, что вы можете использовать шаблоны для использования с использованием контейнеров switch-in/switch-out, не прибегая к ужасающему беспорядку, который является интерфейсами Java.

+2

Нет, вы не можете. Когда-нибудь прочитайте «Эффективный STL». Каждый контейнер в настоящее время достаточно разный, что вы не можете, скажем, поменять список для вектора. В Java вы можете поменять LinkedList на ArrayList, и интерфейс (List) не изменился. – KitsuneYMG

+0

Зависит от того, на каком уровне вы пытаетесь их использовать. Я просто использовал вектор и вектор . – Puppy

3

STL дает вам куски.

Языки и их окружения построены из небольших компонентов, иногда через конструкции языка программирования, иногда с помощью вырезания и вставки. Некоторые языки предоставляют, например, закрытую коробку - коллекции Java. Вы можете делать то, что они позволяют, но горе вам, если вы хотите сделать что-то экзотическое с ними.

STL дает вам части, которые дизайнеры использовали для создания более совершенных функций. Непосредственное отображение итераторов, алгоритмов и т. Д. Дает вам абстрактный, но чрезвычайно гибкий способ рекомбинирования структур данных ядра и манипуляций любым способом, который подходит для решения вашей проблемы. Хотя дизайн Java, вероятно, поражает отметку 90-95% для того, что вам нужно от структур данных, гибкость STL повышает ее до 99%, а абстракция итератора означает, что вы не полностью используете свои ресурсы для оставшихся 1%.

Когда вы совмещаете это с его скоростью и другими возможностями расширяемости и customizabiltiy (распределители, черты и т. Д.), У вас есть отличный пакет. Я не знаю, что я назвал бы его лучшим пакетом структур данных, но, безусловно, очень хорошим.

Предупреждение: проценты полностью составлены.

+0

Как это отличается от любой другой библиотеки коллекций? –

+0

@Billy Комбинированные алгоритмы и итераторы позволяют создавать вещи из меньших частей. Возьмите двоичный поиск: Java дает вам двоичный поиск, который находит соответствующий элемент. Что делать, если есть несколько совпадающих элементов? C++ дает два метода: lower_bound и upper_bound, которые находят нижние и верхние ограничивающие итераторы смежного диапазона совпадающих элементов. Если вам нужен краткий случай из нескольких элементов, Java оставляет вас почти висящими. –

2

Очевидно, что C++, C# и Java могут вводить столько мошеннических конкурсов, сколько вы хотите. Ключ о том, почему STL, по крайней мере, несколько отличен, заключается в том, что Java изначально была разработана и реализована без контейнеров без типов. Затем Sun решила/поняла, что люди действительно нуждаются в них на типизированном языке, и добавили дженерики в 1.5.

Вы можете сравнить плюсы и минусы каждого, но что касается того, какой из трех языков имеет «наибольшую» реализацию универсальных контейнеров - это исключительно конкурс мошенников. Величайший для чего? По мнению? У каждого из них есть лучшие библиотеки, которые создатели смогли создать, с учетом других ограничений, налагаемых языками. Идея C++ о генериках не работает в Java, и стирание типа будет нестандартным при типичном использовании C++.

0

Если вы не видите, что такое использование STL, я рекомендую купить книгу «Язык программирования C++» Бьярне Страуструпа. Это в значительной степени объясняет все, что есть о C++, потому что он чувак, который его создал.

+0

Я уверен, что Чувак должен плакать тайно за то, что комитет сделал с его языком. – Zygrob

+0

@ Zygrob: Возможно, но это не так, как будто не имеет голоса: он - комитет. –

Смежные вопросы