Практично ли отказываться от STL в разработке на C ++? [закрыто]

19

Я знаю, что в некоторых областях (например, в игровой индустрии) STL не рекомендуется. Итак, мой вопрос: действительно ли хорошая практика не использовать STL в некоторых случаях? Если да, то каковы основные причины неиспользования STL современного C ++?

CaptainJH
источник
некоторые из моих коллег утверждают, что итератор усложняет отладку, потому что иногда это не так просто сделать, и это также относится к лямбде. Каков твой ответ?
CaptainJH
Что касается пропуска материала во время отладки, см., Например: stackoverflow.com/questions/2062881/…
Martin Ba
Это кажется хорошим вопросом. Может быть, кто-то может добавить: «Почему проект решил не использовать STL?»
Мэтью Джеймс Бриггс

Ответы:

25
  • Я могу придумать только одну вескую причину, и она действительно редка: трудно в реальном времени. Многие вещи в стандартной библиотеке выделяют память внутренне, и это недостаточно детерминировано для жестких приложений реального времени, поэтому их следует избегать. Эти приложения, как правило, довольно просты, хотя для их разработки требуется непропорциональное время из-за очень тщательного анализа и тестирования.

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

    STL обычно быстрее во время выполнения, чем либо решения в стиле C с указателями обратного вызова, либо решения на основе полиморфизма с виртуальными методами ( см. Также эту заметку Бьярна Страуструпа ). Однако, когда разработчик не понимает заданные спецификации сложности и неправильно использует библиотеку, создавая что-то вроде вектора векторов некоторых сложных объектов (хотя в C ++ 11 это уже не проблема!), Это вызывает проблемы с производительностью и защищает себя. с «вы видите, векторы довольно медленные», это может вызвать ощущение, что стандартная библиотека медленная. И как только менеджеры получают такое восприятие, они могут очень долго жить в организации.

  • Очевидно, что вы не можете использовать то, что не поддерживает целевая платформа. Однако в настоящее время мы нацелены на четыре наиболее распространенные мобильные платформы (Android, iOS, Bada и старый WinCE) и используем стандартную библиотеку и некоторые части Boost на всех из них.

    Большая часть стандартной библиотеки раньше не поддерживалась Microsoft в начале WinCE (IIRC iostreams вышел только с Visual Studio 2005), но вместо этого было возможно использовать STLport задолго до этого. И вы обычно можете получить это, чтобы скомпилировать что-нибудь. Поэтому я бы назвал эту причину недействительной.

    Кроме того, довольно долго это не "STL", а стандартная библиотека ANSI C ++. Это определяется тем же стандартным документом, который определяет сам язык. Все, что не поддерживает это, на самом деле не заслуживает того, чтобы называться C ++.

Ян Худек
источник
6
Первый аргумент (в реальном времени) не относится к частям стандартной библиотеки STL. sprintfчасто выделяет память тоже. На платформах реального времени стандартные функции библиотеки также имеют детерминированные ограничения. Это усложняет реализацию C ++ в реальном времени: вам нужно тщательно разработать целую стандартную библиотеку C ++, которая является более сложной работой, чем просто небольшая стандартная библиотека C.
MSalters
@MSalters: Конечно, многие вещи нельзя использовать в режиме реального времени. Даже некоторые языковые функции, такие как исключения, не могут. Тем не менее C ++ является отличным языком для этих систем, потому что он может сочетать производительность и точное управление с надежными мерами защиты (RAII является наиболее важной функцией для этого).
Ян Худек
@JanHudec: Действительно, именно поэтому части STL требуются только для "размещенных" реализаций C ++.
MSalters
7

Я использую STL и Boost уже много лет. Если бы я хотел отказаться от него и использовать свои собственные инструменты, мотивация была бы:

  1. Сокращение времени компиляции (75%). Только включение iostreams может добавить 1 миллион строк кода в ваш модуль. Да, прекомпилированные заголовки очень помогают, но это все же сильно тормозит компиляцию в больших проектах. В конечном счете, это тратит впустую много времени любого, кто над этим работает.
  2. Производительность. (25%) STL написан для работы в целом, но вы можете оптимизировать свои структуры для работы именно так, как вы хотите. Например, у вас могут быть структуры данных с миллионами коротких строк. Возможно, будет гораздо быстрее использовать пользовательский класс строк на основе принципа boost :: small_vector (небольшой статический локальный вектор данных, динамическое выделение только для больших строк), изменения такого рода могут заставить критические участки кода работать во много раз быстрее.
Марвин
источник
1
SSO уже распространен.
Дедупликатор
для потомков: SSO -> оптимизация небольших строк, т. е. большинство (все?) реализаций std :: string сохраняют небольшие строки в стеке и, если необходимо, переключаются в кучу
синий
Время компиляции большое
user1754322
4

Есть одна веская причина не использовать стандартную библиотеку шаблонов C ++: одна из ваших целевых платформ не имеет полностью соответствующей реализации (или вообще не имеет ее реализации), и вы знаете, что она не получит ее в течение следующих лет.

Патрик
источник
3
Ака "не используйте его, когда у вас его нет", что действительно имеет смысл. :)
Xeo
4
Учитывая, что стандартная библиотека C ++ 03 предназначена для реализации только в рамках библиотеки ANSI C89, существует ли какая-либо платформа, на которой вы не смогли бы получить хотя бы STLPort ?
Ян Худек
@JanHudec Я считаю, что есть платформы без STL, потому что у них недостаточно памяти для обработки всего этого. Обычно они также пропускают некоторые другие функции C ++ (например, исключения).
Sulthan
2
@Sulthan: Для микроконтроллеров я вроде как понимаю, но они обычно попадают в категорию «hard realtime». Во всем остальном это в основном предвзятые мнения, потому что STL обычно так же эффективен как с точки зрения памяти, так и с точки зрения производительности, как код, созданный вручную. Множество встраиваний может привести к увеличению размера двоичного файла, но этого можно было бы избежать путем тщательной реализации с некоторыми затратами на производительность (что было бы также и у решения, созданного вручную). Пропущенные исключения также являются либо предвзятым мнением, либо ленью, потому что для определения и реализации исключения ABI требуются усилия.
Ян Худек
4

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

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

Джорджио
источник
2
эквиваленты Qt были созданы еще тогда, когда не было реализаций STL, которые были бы либо a) доступны, либо b) не годились. Это единственная причина, по которой они все еще используются, ничто против сегодняшнего STL.
gbjbaanb
1
@ Джорджио: проблема в сложных приложениях, где вы объединяете несколько библиотек. Контейнеры STL, будучи стандартными, образуют лингва франка . Точнее, это их соглашения, которые делают. Самый известный пример - Boost. Может работать на контейнерах STL. он также может работать на контейнеры Qt, но только потому , что Qt имеет следующие условные STL - напримерQList<T>::iterator
MSalters
3
Я не отрицал это, но вижу одну причину: это не отвечает на вопрос. Вы сказали, что есть вещи, которые нужно использовать вместо STL, хорошо, но это не причина избегать STL. Кроме того, любая причина избегать STL, вероятно, применима и к Qt, MFC и другим подобным библиотекам или даже больше.
Ян Худек
3
@NoOne: Мы понимаем, что вы привыкли к верблюжьему, а не змеиному, но это не делает последнее хуже. И из трех названий функций, которые вы критикуете, первое совершенно описательно для тех, кто имеет какое-либо отношение к c-строкам, а два других унаследованы от C, обсуждать их не будем.
дедупликатор
1
@NoOne: Как я уже сказал, я полностью понимаю, что вам удобнее с CamelCase.
дедупликатор
3

Патрик упомянул причину не использовать весь STL, а именно, что ваша платформа (ы) не имеет его.

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

Мартин Ба
источник
3

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

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

«Каждая успешная игра начинается с развертывания собственной реализации связанного списка».

zxcdw
источник
1
Я мог бы представить, что каждая успешная игра начинается с написания кода с использованием стандартной библиотеки, а затем оптимизации кода только после того, как игра была тщательно профилирована. Оптимизация до того, как вы получите данные профилирования с указанием того, что нужно оптимизировать, бессмысленна
Cromulent
Правда. Последняя фраза была просто игрой о «древнем» способе написания игр в начале 90-х или около того, когда C ++ не был так широко распространен, и ассемблер + C был подходящим вариантом. Возможно, я должен был сделать это более ясным. Это хорошо подходит для игровой индустрии в консолях, хотя большинство алгоритмов и структур данных по умолчанию написаны от руки, потому что учитывается каждый байт и цикл (да, даже за счет удобства обслуживания / переносимости / чего бы то ни было).
zxcdw
2
Надо сказать, что это больше старый опыт жизни на. Современный оптимизатор, как правило, генерирует лучшую сборку из простого обслуживаемого кода, чем программист вручную, а универсальные шаблоны, такие как STL или Boost, часто встроены в столь же эффективный код, как и специальный корпус вручную. Но есть много кода, который начинался во времена, когда это было не так, и множество людей, которые изучали торговлю в те дни и продолжают работать таким образом, даже если это больше не имеет смысла.
Ян Худек
2
@JanHudec Дело в том, что реализации (и поведение, также, на самом деле) должны быть очень адаптированы для этой задачи. Вы просто не можете сэкономить несколько десятков байт тут и там (разрушая местность ссылок), добавить несколько веток для проверки ввода (ошибочные прогнозы веток и ошибки в кэше инструкций) и предположить, что компилятор знает, как векторизовать ваши структуры данных оптимально использовать SIMD (это не так, или, по крайней мере, вы должны проверить, что то, что он пытается сделать правильно). Конечно, написание программного обеспечения для реального времени на ПК не так строго, вы всегда можете добавить более быстрый процессор. Не в консолях.
zxcdw