Хорошая Идея / Плохая Идея Должен Ли Я Переосмыслить Большую Часть C++? [закрытый]


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

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

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

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

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

Повторное использование boost или similiar.

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

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

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

Формат.

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

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

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

20 ответов:

Итак, почему бы мне не реализовать меньше общий, но более простой в использовании вариант?

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

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

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

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

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

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

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

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

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

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

Распределители можно смело игнорировать. Вам даже не нужно знать, что они существуют. Итераторы, однако, блестящи, и их вычисление избавит вас от многих головных болей. Есть только три понятия, которые вам нужно понять, чтобы использовать STL эффективно:
  • контейнеры: вы уже знаете об этом. векторы, связанные списки, карты, наборы, очереди и так далее.
  • Итераторы: абстракции, позволяющие перемещаться по контейнеру (или подмножествам контейнера, или любой другой последовательности значений, в памяти, на диске в виде потоков или вычисляемых на лету).
  • алгоритмы: общие алгоритмы, работающие налюбой паре итераторов. У вас есть сортировка, for_each, find, copy и многие другие.

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

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

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

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

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

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

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

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

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

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

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

Первый

Я думаю, что вы должны это сделать.

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

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

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

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

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

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

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

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

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

Посмотрите здесь и, если вы используете VisualC, также здесь.

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

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

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

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

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

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

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

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

Еще Один Недостаток:

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

Недостаток:

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

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

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

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

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

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

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

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

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

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

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

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

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

Повторное использование boost или similiar.

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

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

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

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

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

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

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

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

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

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

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

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

Некоторые примеры для более быстрого/легкого использования без STL:

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

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

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

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

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

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