Хорошая идея/плохая идея. Стоит ли переопределить большую часть C++?[закрыто]

StackOverflow https://stackoverflow.com/questions/637986

Вопрос

Недавно после прочтения мне в голову пришла опасная идея. этот Сообщение блога.Эту идею можно выразить так:

Мне не нужна большая часть того, что предлагает стандартная библиотека C++.Итак, почему бы мне не реализовать менее общую, но более простую в использовании версию?

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

Что я хотел бы узнать от сообщества StackOverflow:каковы опасности, возможные недостатки и возможные преимущества «развертывания своих собственных» для большинства существующих функций C++?

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

Повторное использование повышения или аналогичного.

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

Объективность этого вопроса.

Этот вопрос нет субъективный.И это не должно быть Wiki-сообщество, поскольку это не опрос.Мне нужны конкретные аргументы, подчеркивающие одно преимущество или один недостаток, которые могли бы возможно происходят с моим подходом.Вопреки распространенному мнению, это не мнение, а основанное на опыте или хороших логических аргументах.

Формат.

Пожалуйста, напишите только один недостаток или одно преимущество за ответ.Это позволит людям оценивать отдельные идеи, а не все ваши идеи сразу.

И пожалуйста...

Никаких религиозных войн.Я не фанат какого-либо языка.Я использую все, что применимо.Для сжатия графики и данных (над чем я сейчас работаю) это, кажется, C++.Пожалуйста, ограничьте свои ответы на вопрос, иначе они будут отклонены.

Это было полезно?

Решение

Итак, почему я не внедряю менее общую, но проще в использовании версии?

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

Честно говоря, ваш выбор прост:

Изучите C++ или не используйте его.Да, C++ обычно используется для графики, но в Java также есть библиотеки OpenGL.То же самое касается C#, Python и практически любого другого языка.Или С.Вам не обязательно использовать C++.

Но если вы его используете, изучите его и используйте правильно.

Если вам нужны неизменяемые строки, создайте строку как const.

И независимо от базовой реализации, STL удивительно прост в использовании.

Ошибки компилятора C++ может можно прочитать, но это требует некоторой практики.Но что еще более важно, они не являются эксклюзивными для кода STL.Вы столкнетесь с ними независимо от того, что вы делаете и какие библиотеки используете.Так что привыкайте к ним.И если вы все равно к ним привыкнете, вы также можете использовать STL.

Помимо этого, еще несколько недостатков:

  • Никто больше не поймет ваш код.Если вы зададите вопрос на SO о std::vector или двунаправленных итераторах, каждый, кто достаточно знаком с C++, сможет ответить.Если вы спросите о My::CustomLinkedList, никто не сможет вам помочь.И это прискорбно, потому что создание собственного также означает, что будет больше ошибок, по поводу которых можно будет обратиться за помощью.
  • Вы пытаетесь вылечить симптом, а не причину.Проблема в том, что вы не понимаете C++.STL — всего лишь симптом этого.Отказ от STL не улучшит работу вашего кода C++ волшебным образом.
  • Ошибки компилятора.Да, их противно читать, но они есть.Большая работа в STL была проделана для того, чтобы гарантировать, что неправильное использование в большинстве случаев приведет к ошибкам компилятора.В C++ очень легко создать код, который компилируется, но не работает.Или кажется, что работает.Или работает на моем компьютере, но загадочным образом выходит из строя в другом месте.Ваш собственный связанный список почти наверняка перенесет больше ошибок во время выполнения, где они какое-то время останутся незамеченными, и их будет гораздо труднее отследить.
  • И снова будет глючить.Поверьте мне.Я видел чертовски хороших программистов на C++, которые писали связанный список на C++ только для того, чтобы обнаружить ошибку за ошибкой, в неясных пограничных случаях.А C++ — это все пограничные случаи.Будет ли ваш связанный список правильно обеспечивать безопасность исключений?Будет ли это гарантировать, что все находится в согласованном состоянии, если создание нового узла (и тем самым вызов конструктора типа объекта) выдает исключение?Что не будет утечки памяти, что будут вызваны все соответствующие деструкторы?Будет ли он таким же типобезопасным?Будет ли он таким же производительным?При написании контейнерных классов на C++ возникает множество проблем.
  • Вы упускаете одну из самых мощных и гибких существующих библиотек: любой язык.STL может сделать многое, что было бы затруднительно даже с гигантской раздутой библиотекой классов Java.C++ уже достаточно сложен, и нет необходимости отказываться от тех немногих преимуществ, которые он предлагает.

Меня не волнует распределителей, итераторов и тому подобное

Распределители можно смело игнорировать.Вам даже не обязательно знать, что они существуют.Однако итераторы великолепны, и их понимание избавит вас от многих головных болей.Чтобы эффективно использовать STL, вам необходимо понять всего три концепции:

  • Контейнеры:Вы уже знаете об этом.векторы, связанные списки, карты, множества, очереди и так далее.
  • Итераторы:Абстракции, позволяющие перемещаться по контейнеру (или подмножествам контейнера, или по любой другой последовательности значений в памяти, на диске в виде потоков или вычисляться на лету).
  • Алгоритмы:Общие алгоритмы, которые работают на любой пара итераторов.У вас есть сортировка, for_each, поиск, копирование и многие другие.

Да, STL невелика по сравнению с библиотекой Java, но она обладает удивительной мощью, если объединить три вышеупомянутые концепции.Это своего рода кривая обучения, потому что это необычная библиотека.Но если вы собираетесь провести с C++ больше одного-двух дней, стоит изучить его как следует.

И нет, я не следую вашему формату ответа, потому что подумал, что на самом деле дать вам подробный ответ будет полезнее.;)

Редактировать:

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

Как я уже говорил выше, легко написать код на C++, который кажется работать.А когда он перестает работать, можно легко изменить некоторые вещи, например порядок объявления переменных, или вставить немного отступов в класс, чтобы сделать его по-видимому опять работа.Чему бы вы научились из этого?Научит ли это вас, как лучше писать на C++?Возможно.Но, скорее всего, это просто научит вас, что «C++ — отстой».Научит ли он вас использованию STL?Точно нет.Более полезным подходом может быть использование удивительных возможностей StackOverflow для правильного изучения STL.:)

Другие советы

Недостаток: никто, кроме тебя, этим не воспользуется.

Преимущество: В процессе реализации вы узнаете, почему Стандартная библиотека — это хорошо.

Преимущества:ешь свой собственный собачий корм.Вы получаете именно то, что делаете.

Недостатки:ешь свой собственный собачий корм.Многие люди, умнее 99% из нас, потратили годы на создание STL.

Я предложил вам узнать, почему:

Использование STL выплевывает множество непостижимых и изуродованных ошибок компилятора

первый

Недостаток:вы можете потратить больше времени на отладку библиотеки классов, чем на решение университетской задачи, стоящей перед вами.

Преимущество:вы, вероятно, многому научитесь!

Есть кое-что, что вы можете сделать с загадочными сообщениями об ошибках STL компилятора.STLFilt поможет их упростить.Из Сайт STLFilt:

STLFILT упрощает и/или переформатирует многословную ошибку C ++ и предупреждающие сообщения, с акцентом на диагностику, связанную с STL (и для MSVC 6 он полностью исключает предупреждения C4786 и их детрит).Результат делает многие из самых загадочных диагностей понятной.

Взгляни здесь и, если вы используете VisualC, также здесь.

Я думаю, тебе следует это сделать.

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

STL — отличная библиотека, но я знаю из собственного опыта, что если вы создадите свою собственную, вы сможете:

1) Сделайте его быстрее, чем STL, для ваших конкретных случаев использования.2) Вы напишете библиотеку только с теми интерфейсами, которые вам нужны.3) Вы сможете расширить все стандартные возможности.(Я не могу сказать вам, как сильно мне хотелось, чтобы у std::string был метод Split())...

Все правы, когда говорят, что работы будет много.Это правда.

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

Недостаток :ИМХО, переопределение протестированных и проверенных библиотек - это черная дыра, которая почти гарантированно принесет больше проблем, чем пользы.

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

Поскольку мне нужна была универсальность, я создал шаблонный массив.

Я также хотел выполнить итерацию, не используя оператор[], а увеличивая указатель, как это было бы с C, поэтому я не вычисляю адрес T[i] на каждой итерации...Я добавил два метода: один для возврата указателя на выделенную память, а другой — для возврата указателя на конец.Чтобы перебрать массив целых чисел, мне пришлось написать что-то вроде этого:

for(int * p = array.pData(); p != array.pEnd(); ++p){
  cout<<*p<<endl; 
}

Затем, когда я начинаю использовать векторы векторов, я понимаю, что когда это было возможно, можно было выделить большой блок памяти вместо многократного вызова new.На данный момент я добавляю распределитель в класс шаблона.

Только тогда я замечаю, что написал совершенно бесполезный клон std::vector<>.

По крайней мере, теперь я знаю, почему я использую STL...

Другой Недостаток:

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

Недостаток:

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

Возможно, вас заинтересует ИСТЛ, переписанная версия STL Electronic Arts, задокументированная некоторое время назад.Их дизайнерские решения в основном были обусловлены конкретными желаниями/потребностями в программировании мультиплатформенных видеоигр.Аннотация в связанной статье прекрасно подводит итог.

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

Преимущество

Если вы заглянете в MFC, вы обнаружите, что ваше предложение уже используется в продуктивном коде — и так было уже долгое время.Ни один из классов коллекций MFC не использует STL.

Почему бы вам не взглянуть на существующие библиотеки C++.В те времена, когда C++ еще не был таким зрелым, люди часто писали свои собственные библиотеки.Взгляните на Symbian (хотя это довольно ужасно), Qt и WxWidgets (если мне не изменяет память) имеют базовые коллекции и прочее, и, вероятно, есть много других.

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

В качестве примера, используя STL, выплющивает множество непостижимых и изуродованных ошибок компилятора

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

Вы можете создавать контейнеры, не основанные на шаблонах, и хранить все как указатели void или какой-либо базовый класс, например.Но вы потеряете проверку типов во время компиляции, а C++ как динамический язык — отстой.Это не так безопасно, как, например.Objective-C, Python или Java.Одна из причин заключается в том, что в C++ нет корневого класса для всех классов для самоанализа всех объектов и некоторой базовой обработки ошибок во время выполнения.Вместо этого ваше приложение, скорее всего, выйдет из строя и сгорит, если вы ошибетесь в выборе типа, и вам не будет дано никаких подсказок о том, что пошло не так.

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

каковы опасности, возможные недостатки и возможные преимущества «развертывания своих собственных» для большинства существующих функций C++?

Можете ли вы позволить себе и, возможно, оправдать количество усилий/времени/денег, потраченных на изобретение велосипеда?

Повторное использование повышения или аналогичного.

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

О том, чтобы не «изобретать велосипед»

Недостаток: Хотя вы многому учитесь, вы также отбрасываете себя назад, когда начинаете думать о том, каковы ваши настоящие цели проекта.

Преимущество: Обслуживание проще для людей, которые унаследуют это.

STL очень сложен, поскольку он должен быть предназначен для библиотеки общего назначения.

Причины, по которым STL такой, какой он есть:

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

Однако во многих приложениях вам действительно достаточно следующего:

  • строковый класс
  • хеш-таблица для поиска O(1)
  • вектор/массив с сортировкой/и бинарным поиском для отсортированных коллекций

Если вы это знаете:

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

Тогда вы, вероятно, сможете написать свой собственный более быстрый код, который использует меньше памяти и выдает более простые ошибки компиляции/выполнения.

Несколько примеров быстрее/проще без STL:

  • Строка копирования при записи со строковым буфером с подсчетом ссылок.(Не делайте этого в многопоточной среде, поскольку вам потребуется заблокировать доступ к счетчику ссылок.)
  • Используйте хорошую хеш-таблицу вместо std::set и std::map.
  • Итераторы в стиле Java, которые можно передавать как один объект.
  • Тип итератора, которому не обязательно знать тип контейнера (для лучшего разделения кода во время компиляции).
  • Строковый класс с большим количеством служебных функций.
  • Настраиваемая проверка границ в векторных контейнерах.(Поэтому не [] или .at, а тот же метод с флагом компиляции или времени выполнения для перехода из «безопасного» в «быстрый» режим)
  • Контейнеры, предназначенные для работы с указателями на объекты, которые удаляют их содержимое.

Похоже, вы обновили вопрос, поэтому теперь действительно два вопроса:

  1. Что мне делать, если я думаю, что std::библиотека слишком сложна для моих нужд?

Создайте свои собственные классы, которые внутренне используют соответствующий std::функции библиотеки, которые сделают за вас «тяжелую работу».Таким образом, у вас будет меньше ошибок, и вы все равно сможете изобрести свой собственный интерфейс кодирования.

  1. Что мне делать, если я хочу узнать, как работают структуры данных?

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top