LINUX.ORG.RU

10 причин почему программист на С++ может выбить много денег


24

10

Список в конце поста написан Лавсаном 2 года назад. (2011-03-23 19:56:00) (источник)
Надеюсь, автор не подаст жалобу в Роспатент за перепечатку :-)
Кстати, sudo cast lovesan.

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

Временное резюме: С++ всё еще актуален по историческим причинам. Еще есть мобилки (sudo cast mono), гиперкластеры для шиндовс 3.11 (sudo cast vromanov) и базы данных. Т.к. он актуален, но не предназначен ни для чего (см. выводы в конце списка) новых специалистов по нему должно быть мало. Маленькая конкуренция на огромной области применения — огромное лавэ $$$. Вот это и есть истинная причина использовать кресты — возможность срубить €€€.

Честно говоря, «хитрый план» мне уже очень надоел, поэтому пора открыть карты.

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

Вот этот список:

  1. Вырвиглазный синтаксис и контекстно-зависимая грамматика
    • медленная компиляция
    • частые «internal error» в компиляторах
    • код плохо читается и его сложно поддерживать
    • разбор кода различными инструментами, вроде IDE, и его генерация - сильно затруднены
  2. ручное управление памятью
    • неудобства при работе с динамической памятью
    • утечки памяти
    • висячие ссылки
    • сегфолты
    • стандартные средства, как то malloc/new, работают медленно
    • фрагментация кучи
    • велосипедные аллокаторы на каждом шагу
      • которые далеко не факт что эффективнее malloc/new

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

    • отладка затруднена
    • написание GC, по факту, невозможно, отчасти из-за (5), (7) и (8)
  3. Никакого ABI
  4. Нестандартизированный и непредсказумый name mangling
  5. Дублирование функционала Си
    • сами фичи из Си никуда не деваются при этом
      • отчасти из-за того, что по функционалу превосходят аналоги из C++

    • запутывает новичков
    • malloc - new/new[], free - delete/delete[]
    • препроцессор - шаблоны
    • указатели - ссылки
      • ссылка не может быть NULL, что способствует появлению висячих ссылок и сегфолтов

    • структуры - классы
    • stdio - iostream
  6. Стандартная библиотека убога
    • Отсутствует даже такой функционал, как вменяемая работа со строками и многомерные массивы
      • Юникод?

  7. Слабая типизация
    • способствует ошибкам
    • затрудняет отладку
    • const не дает абсолютно никаких гарантий
    • при этом система типов невероятно переусложенена
      • в основном из-за пунктов (2), (5) и (9)
      • медленная компиляция
      • частые внутренние ошибки в компиляторах

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

    • множественное наследование неудобно в использовании
      • проблема ромба по дефолту не разрешается никак

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

    • деструктор можно вызывать до выхода из блока кода, или до delete
      • гарантированная утечка ресурсов/сегфлот
      • это не предотвратить никак, деструктор обязан быть public

    • одиночная диспетчеризация
      • виртуальные методы в конструкторах не работают
      • реализована убого
        • pure virtual function call
        • сложности в случае с множественным наследованием
        • деструкторы обязаны быть виртуальными
          • по дефолту - не виртуальные

        • никаких интерфейсов, только классы

    • порядок инициализации статических членов классов не определен
    • private, public и protected не дают никаких гарантий сокрытия данных
      • к инкапсуляции же не относятся совершенно никак

    • отсутствие «свойств»
      • вынуждает городить getter'ы и setter'ы
        • раздувание кода
        • размывание интерфейса класса

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

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

    • позволяют генерировать некорректный код
  10. исключения
    • отсутствие finally/unwind-protect
      • заставляет городить классы ради одних деструкторов
        • раздувание кода
        • медленная компиляция
        • медленная работа

    • конфликтуют с другими возможностями языка
      • конструкторы/деструкторы
      • ручное управление памятью

    • работают медленно
    • малофункциональны (ср. CL condition system)

По причинам 3, 4, 5, 9 и 10 C++ совершенно неприменим для системного и низкоуровневого программирования. А по причинами 1, 2, 5, 6, 7, 8, и, опять же, 9 и 10 - и для прикладного.

У C++ нет области применения.

★★★★☆

Последнее исправление: stevejobs (всего исправлений: 1)
Ответ на: комментарий от stevejobs

Initialization discards qualifiers from pointer target type

компилировать надо с -Wall

не-const указатель ptr автоматически отменяет оператор const у переменной three

mazdai ★★★
()
Ответ на: комментарий от stevejobs

какие оценки у тебя были по математической логике, математической/компьютерной лингвистике, построению компиляторов? «неуды»?

Тебе попытались объяснить на пальцах что такое UB. Оперируя «логикой» такое описать достаточно сложно. Можно сказать по-другому - РЕЗУЛЬТАТ НЕПРЕДСКАЗУЕМ :)

anonymous
()
Ответ на: комментарий от anonymous

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

ты немного не понимаешь, что такое «приказ». Приказы ВСЕ не обсуждаются. Например:

Приказ №1: не расстреливать мирное население

Приказ №2: расстрелять квадрат 1366.

Так вот, даже если командир расчёта артиллерии знает, что в 1366 мирное население, он всё равно приказ выполнит. Потому-что это ПРИКАЗ, и его сведения неверные. По новым данным разведки в 1366 — хорошо замаскированный вражеский объект. И если его ВНЕЗАПНО не уничтожить, то уничтожат всю армию. В т.ч. и шибко умного артиллериста. Потому артиллерист даже и думать не будет, а уверенно сравняет 1366 с землёй.

И кого будут за это судить? Тебя, ЧСХ.

Ну так проблема в том, что как раз не делает. Ему сказали «не генерируй код, который может изменить значение этой переменной». А он генерирует.

Правильно делает. Ибо твои приказы противоречат один другому. Ты быдлокодер, и твой компилятор создаёт быдлокод.

emulek
()
Ответ на: комментарий от anonymous

Он это проверять должен при компиляции

в какой части стандарта прописано это твоё «должен»?

emulek
()
Ответ на: комментарий от anonymous

Очевидно, что если в структуре есть const поле то запись в нее по указателю запрещена. Ну, должна быть запрещена.

вот именно поэтому не разрешается двигать указатели ЗА пределы указываемого объекта. Кроме того, не разрешается менять тип указателя, скажем из const в неconst.

Если ты так сделал, то по стандарту — неопределённое поведение. Т.е. — неизвестно что. HEX.

emulek
()
Ответ на: комментарий от wota

эта та же самая адресная арифметика, которую ты хотел запретить

он правильно её хочет запретить, ибо в стандарте она УЖЕ запрещена. Вот только ты об этом не знаешь. Ибо быдлокодер. А компилятор не обязан знать, что код писал быдлокодер, и исправлять его ошибки, и его безграмотность.

питон --> там.

emulek
()
Ответ на: комментарий от anonymous

А вот когда оно специфицировано и меняет константное значение - это фейл.

фэйл только в ваших влажных фантазиях. В C/C++ это запрещено. Точка.

emulek
()
Ответ на: комментарий от anonymous

Дело не в говнокоде, а в том, что компилтяор языка не выполняет отданные ему команды. Сказали константа - значит константа. Или тогда убирайте этот модификатор

лучше ты выпей йаду.

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

Разве компилятор должен предупреждать тебя, что ты тупишь?

emulek
()
Ответ на: комментарий от wota

у тебя примеры УЖЕ с UB. Какой от них прок?

В стандарте написано UB? Всё, разговор окончен, автор кода получает клеймо «быдлокодер», и бежит радостно штудировать стандарт.

Ну или остаётся счасливой пхп-обезьяной.

Каждому своё.

emulek
()
Ответ на: комментарий от emulek

Правильно делает. Ибо твои приказы противоречат один другому. Ты быдлокодер, и твой компилятор создаёт быдлокод.

а должен написать фатал еррор и остановиться с подробным объяснением, что чему противоречит

stevejobs ★★★★☆
() автор топика
Ответ на: комментарий от emulek

анонимус> компилятор виноват - разрешил
я> дурак путь найдет, даже если компилятор в данном случае явно запретит, например можно так <...>
анонимус> запретить вообще писать по указателю в структуру с const
я> а вот так все равно можно записать по нужному адресу <...>
негодующие фанатики> аааа!! быдлокодерство!!!! UB!!!

а речь шла всего-лишь о компиляторе - может и должен ли он давать по рукам в таких случаях

wota ★★
()
Ответ на: комментарий от stevejobs

Правильно делает. Ибо твои приказы противоречат один другому. Ты быдлокодер, и твой компилятор создаёт быдлокод.

а должен написать фатал еррор и остановиться с подробным объяснением, что чему противоречит

повторяю:

питон --> там.

вон из моей сишечки.

emulek
()
Ответ на: комментарий от wota

я> а вот так все равно можно записать по нужному адресу <...>

ты спалился на слове «можно».

НЕЛЬЗЯ.

а речь шла всего-лишь о компиляторе - может и должен ли он давать по рукам в таких случаях

а компилятор тут не причём. Ты же не ругаешь калькулятор за то, что он на ноль делить «не умеет»? Тут тоже самое.

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

emulek
()
Ответ на: комментарий от emulek

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

stevejobs ★★★★☆
() автор топика
Ответ на: комментарий от emulek

ты спалился на слове «можно».
НЕЛЬЗЯ.

какой ты нервный, еще раз - речь не шла про стандарт и UB, речь шла про запись значения по адресу, и именно то, что она прошла и смущает анонимуса

а компилятор тут не причём

да - причем стандарт с массой UB, вот ты, например, используешь const cast в С или С++? если да - в каких случаях?

Ты же не ругаешь калькулятор за то, что он на ноль делить «не умеет»?

не ругаю, он мне ошибку покажет, анонимус это и хотел

wota ★★
()
Ответ на: комментарий от stevejobs

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

anonymous
()
Ответ на: комментарий от stevejobs

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

калькуляторы разные бывают. А те, что даунов — да. «Не смогла».

emulek
()
Ответ на: комментарий от wota

какой ты нервный, еще раз - речь не шла про стандарт и UB, речь шла про запись значения по адресу, и именно то, что она прошла и смущает анонимуса

правильно смущает. Я не нервничаю, просто констатирую факт — UB.

да - причем стандарт с массой UB, вот ты, например, используешь const cast в С или С++? если да - в каких случаях?

Если честно, не понимаю, зачем?

не ругаю, он мне ошибку покажет, анонимус это и хотел

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

emulek
()
Ответ на: комментарий от anonymous

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

что тебе мешает обработать этот случай?

emulek
()
Ответ на: комментарий от stevejobs

Во первых не сегфолтится акидает sigfpe. Во вторых делает это процессор аппаратно

ckotinko ☆☆☆
()
Ответ на: комментарий от emulek

Интересно как они добиваются сегфолта при делении на ноль, когда там другой сигнал. Мастера говнокода, стопудово

ckotinko ☆☆☆
()
Ответ на: комментарий от ckotinko

Интересно как они добиваются сегфолта при делении на ноль, когда там другой сигнал. Мастера говнокода, стопудово

не. Просто их *калькулятор* выдаёт им «делить на ноль нельзя». Про то, что делит ваще-то CPU им неведомо. Что ты хотел от php-обезьян?

Да, вот пруф:

PHP Warning:  Division by zero in t.php on line 2
emulek
()
Ответ на: комментарий от anonymous

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

qulinxao ★★☆
()
Ответ на: комментарий от emulek

Если честно, не понимаю, зачем?

большей частью тяжелое (и кривое) наследие С, взять тот же qsort, на руки нам приходят два const void* (по очевидным причинам), а мы, например, используем «ленивые» значения, т.е. берем указатель, и, если надо, что-то там вычисляем и кладем назад в структуру, что нам делать? правильно - кастим; вот только в тех же плюсах есть нормальный std::sort, есть mutable, если перегрузка функций и методов, и можно было бы и убрать const cast, а не добавлять отдельный оператор под него, ну а теперь уже никто не будет это менять, чтоб не ломать совместимость с горой кода

wota ★★
()
Ответ на: комментарий от qulinxao

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

согласен. Только в MS-DOS совместимых ОС можно спрашивать у администратора, «чё делать, хозяин?». Нормальная система должна самостоятельно решать свои проблемы, или прибить задачу, которая не имеет решения в принципе.

emulek
()
Ответ на: комментарий от wota

большей частью тяжелое (и кривое) наследие С, взять тот же qsort, на руки нам приходят два const void* (по очевидным причинам)

дык сишечка вообще не заточена под ООП. Если нам нужно ООП (манипулировать абстрактными _объектами_), то и получаются монстрики по типу qsort(3). Ещё один похожий монстрик: iconv(3). Тут объектом выступает «строка». Вот так:

       size_t iconv(iconv_t cd,
                    char **inbuf, size_t *inbytesleft,
                    char **outbuf, size_t *outbytesleft);
Это называется: неправильный выбор парадигмы.

Сишечка — достаточно низкоуровневый ЯП, и абстракции типа «какой-то объект», или «какая-то строка» в ней не работают. Можно только сделать абстракцию «хрен знает ваще что», используя void* и прочие костыли.

В этом смысле годен C++, в котором эти вопросы вполне решаемы.

вот только в тех же плюсах есть нормальный std::sort, есть mutable, если перегрузка функций и методов, и можно было бы и убрать const cast, а не добавлять отдельный оператор под него, ну а теперь уже никто не будет это менять, чтоб не ломать совместимость с горой кода

я тебя не понимаю: зачем ты используешь эти костыли? Тебя кто-то заставляет? Просто не используй, и всё. Сам же говоришь, что это «для совместимости со старым кодом». Ты пишешь старый код? TIMEPARADOX?

emulek
()
Ответ на: комментарий от emulek

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

stevejobs ★★★★☆
() автор топика
Ответ на: комментарий от stevejobs

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

хватит врать. Где пруф, что это «моя логика»?

Или ты про то, что сишечка тьюриг-полная, и на ней можно сделать всё что угодно, в т.ч. и ООП? Да, можно. Как и на sed/brainfuck. Вот только я такое предлагал _делать_ исключительно в твоих влажных фантазиях.

emulek
()
Ответ на: комментарий от emulek

я тебя не понимаю: зачем ты используешь эти костыли?

я и не использую, но убрав их можно было бы сделать ЯП чуть проще и прямее, собс-но, что я и имел ввиду

wota ★★
()
Ответ на: комментарий от wota

я и не использую, но убрав их можно было бы сделать ЯП чуть проще и прямее, собс-но, что я и имел ввиду

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

ЗЫЖ эти все костыли потихоньку выпиливаются из C++. Как например ненужное слово auto. В C++11 оно очень даже нужное и полезное. Но с C несовместимо абсолютно.

emulek
()

Господа осилившие прочитать тред, валу упоминали? C++ гавно потому что либы на плюсах очень сложно вызывать из C и прочих языков. Все классы приходится оборачивать в функции и отлавливать все ексепшены возвращая их кодами или по указателю. Раз нет полной совместимости с протоколом разделяемых библиотек ОС то язык уже не низкоуровневый. А смысл от такого убогого языка если он и на звание асемблера не тянет. А вот вала, при том что она почти копия C# по синтаксису (есть даже вещи которые в вале реализовуются в 10 раз короче и кошернее чем в шарпе), абсолютно совместима с C, так как генерит человекочитабельеный код на нем. Мало того либа на вале ничем не отличается от си кода кроме как наличием описания классов. Соответственно написав простой список классов и маппинг имен функций можно ЛЮБУЮ либу на си использовать как вала либу. При этом компилятор настолько умён что при передаче массива передает указатель и размер как 2 параметра однако может быть настроен на юзаж 0-terminated массивов, а к калбекам добавляет поинтер на closure или класс. В результате вала выходит такой няшкой что я готов прощать ей все недоразумения молодого языка (с надеждой однажды починить) такие как невозможность объявлять интерфейс внутри класса (в C++ его вообще нигде не объявишь) и неинициализацию неавтоматических свойств при использовании default (в C++ свойств нет в помине). Кусок гнома на ней уже написан (к примеру игра сапёр и калькулятор). Буду потихоньку переписывать и остальной мир на неё.

q0tw4 ★★★★
()
Ответ на: комментарий от ckotinko

Всяко понятнее того что генерит ecl и тем более хаскель. А если еще вспомнить те веселые имена функций которые генерят плюсы (ну нет в вале перегрузки функций - неизбежная плата за совместимость с си).

q0tw4 ★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.