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)

Ответ на: комментарий от annulen

Это какие-то велосипедные linq2Objects, а где же AST, где expression trees? Где пресловутый SQL хотя бы?

stevejobs ★★★★☆
() автор топика

7. Слабая типизация

Лол что? Это Вы имели ввиду что то похожее на это:

 
int val = 3;
void *p = &val;
*((char*)p) = 'a';

Тогда смею Вас расстроить. Это не слабая типизация. Это как правило кривые руки. Ну или человек ЗНАЕТ, что делает.

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

Ты не знаешь С++ и, видимо, не используешь. Чего зря болтаешь?

anonymous
()

стандартные средства, как то malloc/new, работают медленно

Опять же смею Вас расстроить, ради смеха показал одной девочке-стажеру пример с утечками (т.е. к чему они приводят):

int main(int argc, char** argv)
{
   int* p;
   while(true)
      p = new int(0);
   return 0;
}

Вынесло 1.5 Гб памяти (больше свободной не было) за 3.5 секунды на дерьмовом Целероне с фиговой памятью. На винде 7ке. Стоит упомянуть, что после этого семерка начала по-черному свопить на диск и повисла?

Eric_Nigma
()

Скажу честно - я плюсами уже очень давно не пользуюсь, пишу под C#, тем не менее, я не имею к нему (срр) никаких особых претензий, хотя бы потому что по скорости он, наверно, впереди планеты всей + единственный вменяемый язык для системного программирования (ИМХО). Вы же просто тролль. Ну или хейтер. Вы не понимаете этот язык, не понимаете для чего он нужен? Ну так пишите на том, что Вы считаете удобным и быстрым для себя. И не порите тут чушь. Ну пожалуйста.

Eric_Nigma
()

О, еще одного «осенило», жаль слишком поздно. Надо было предлагать что-то лучше 60 лет назад. А теперь уже поздно - в каждой железке если есть что-то высокоуровневое, то софт это обеспечивающий написан сами знаете на чем, и «благодирить» за это надо сами знаете кого.

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

60 лет назад мы с Фиделем освобождали Кубу и верили в автомат вместо крестов

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

Так вы хотя бы сейчас предложите что-нибудь лучшее. А то вот делаешь прошивку маршрутизатора, и не знаешь что и взять, кроме С или С++(тут правда без эксепшенов и rtti). Или вот сейчас переписывю сервис на питоне, ибо памяти жрет слишком много и никакие напильники не помогают.

D и Go сыроваты, первый к тому же с каким-то странным сборщиком, не говоря уже о переусложненном языке, а последний тормозит почти как java. И да, сборщик должен быть реально опциональным для ниши С++.

Rust?

anonymous
()

Эталонный бред. Либо учись, либо лечись.

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

В rust потенциально тоже сборщик неопционален. А всякие регионы у них есть, но явные и не участвуют в определении моментов освобождения, а служат лишь для обеспечения корректности доступа по ссылкам.

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

Это ты о чем? О «крестах»?

Не следует путать «кресты», aka «плюсы», с православно-правильным С.

Это разные религии.

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

Ну расскажи, чем С лучше С++?

Пространства имен? Перегрузка функций? Позднее связывание без костылей? Обобщенное программирование без костылей? Вывод типов? Лямбды? Исключения? RAII? Ничего нет. При этом в С++ есть все, что есть в С.

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

Чуть менее четверти века тому назад, мне пытались рассказать про «чУдные» идет Страуструпа, aka Трупострауса. Меня тогда не втёрло, и я этому рад.

И программлю я на C и, иногда, даже asm применяю. На современных модных платформах.

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

а последний тормозит почти как java

то, что жаба тормозит - такой же миф как про с, что «по скорости он, наверно, впереди планеты всей». Например, майнинг биткоинов у меня на с работал на 30% медленей асма. Довольно большая разница, не находите? Конечно, майнинг - задача довольно специфическая, но все равно довольно дико смотреть когда (например) люди отказываются от плюсов и более высокоуровневых языков и юзают си, считая сопутствующий гемор платой за прирост в единицы процентов разницы, тогда как заюзывание асма сулит десятки процентов. На мой взгляд, если настолько нужна скорость - юзай асм, а не критична - предпочти удобство.

Причина тому - люди чрезмерно подвержены общественному мнению и традициям, рекламе. Типичные мифы, если взглянуть на них более широко: асм - сложный, си - быстрый, жаба - тормозная, D - сырой, апач - крутой, шарп и пых - удел быдлокодеров... что там еще? Эти все мифы когда-то может имели под собой какую-то реальную основу, но сейчас это больше религия и вопрос доверия тому или иному бренду. А например, в настоящее время рождается следующий миф: вконтакт - для школоты. Может сейчас это реальность а не миф, но лет через 30 школота вырастет, все так же будет там сидеть, но посыл останется.

А то вот делаешь прошивку маршрутизатора, и не знаешь что и взять

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

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

Боюсь, что не получится=)

Вот в парном программировании при решении конкретных задач можно такие вещи объяснять.

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

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

то, что жаба тормозит - такой же миф как про с, что «по скорости он, наверно, впереди планеты всей». Например, майнинг биткоинов у меня на с работал на 30% медленей асма. Довольно большая разница, не находите? Конечно, майнинг - задача довольно специфическая, но все равно довольно дико смотреть когда (например) люди отказываются от плюсов и более высокоуровневых языков и юзают си, считая сопутствующий гемор платой за прирост в единицы процентов разницы, тогда как заюзывание асма сулит десятки процентов. На мой взгляд, если настолько нужна скорость - юзай асм, а не критична - предпочти удобство.

Причина тому - люди чрезмерно подвержены общественному мнению и традициям, рекламе. Типичные мифы, если взглянуть на них более широко: асм - сложный, си - быстрый, жаба - тормозная, D - сырой, апач - крутой, шарп и пых - удел быдлокодеров... что там еще? Эти все мифы когда-то может имели под собой какую-то реальную основу, но сейчас это больше религия и вопрос доверия тому или иному бренду. А например, в настоящее время рождается следующий миф: вконтакт - для школоты. Может сейчас это реальность а не миф, но лет через 30 школота вырастет, все так же будет там сидеть, но посыл останется.

Это не мифы. Просто в некоторых проектах это не сказывается. Я в работе разные языки использую и разницу между ними чувствую.

Асм плох только в плане переносимости. Ну и писать на нем и код поддерживать тяжелее. Си действительно быстрее всех, если убрать асм=) И дело не столько в изначальной скорости, сколько в почти безграничном напильнике. Впрочем, С++(по крайней мере при правильном использовании) бывает быстрее С. Компилятор лучше встраивает шаблонные функции, чем функции по указателю ;)

anonymous
()

Подобного типа священные войны бесполезны. Список какой-то унылый. Никакой конкретики, только общие (и громкие) заявления ничем не подкреплённые.

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

Начиная с неоднозначности a<b,c>d; — это что такое? a<b<c>>d; — а это что? Какой наркоман придумал заюзать угловую скоробочку, которая и так уже в 2 разных значениях использовалась раньше? Наверное, если повыкидать этот сраный уголок, тормозной разбор шаблонов уже ускорится в 9000 раз (ускорится и компилятор, и человек читающий). Зачем это сделано? Да просто так! Во имя Сатаны!

В квотезы.

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

Но это проблема С.

Извините, что? void * — это проблема Си? В Си для этого есть объявления вида struct sometype_t;

Это не проблема C. Это:

наследие кривых интерфейсов

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

Я нихрена не понял, т.к. давно не слежу за развитием языка. Можно для идиотов? В крестах что так и не появилось возможности реализацию специализированной версию шаблона засунуть в объектный файл и выставить наружу символ для экспорта?

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

Попользоваться автомобилем, а потом взять самокат и при помощи мата и скотча пытаться превратить его в подобие автомобиля. C++-way.

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

Попользоваться автомобилем, а потом взять самокат и при помощи мата и скотча пытаться превратить его в подобие автомобиля. C++-way.

но это гораздо лучше чем пользоваться подобием самоката в виде glib ;)

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

рантайм для vala.

самому не смешно? vala умер, так и не родившись

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

Ни разу не пользовался этой фичей, поэтому чисто теория. Зафигачить template в header, а его реализацию в отдельный исходник — выглядит как фича, соответствующая духу крестов. Выставить наружу шаблон, сигнатуры функций, а реализацию спрятать в библиотеке. Проблема в том, что сам код шаблона не имеет смысла без спецификации шаблонных аргументов. Конпелятор не знает, что делать с реализацией до того, как оно где-то будет использовано. Как только конпелятор узнает шаблонные аргументы, он может собрать шаблонный класс. Слово export говорило конпелятору «найди реализацию хоть где-нибудь», Когда компилятор находил реализацию, для каждой из них он собирал шаблонный класс под конкретный набор шаблонных аргументов, и под конкретный же набор шаблонных аргументов сохранял объектный файл.

альтернатива — полная специализация

stevejobs ★★★★☆
() автор топика

Поддерживаю, С хватает за глаза на все задачи.

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

Подобного типа священные войны бесполезны. Список какой-то унылый. Никакой конкретики, только общие (и громкие) заявления ничем не подкреплённые.

Тогда зачем вы читаете тут и пишите сюда? :) подобные «войны» как минимум позволяют узнать настроения, бытующие сегодня в обществе, а так же узнать о новомодных веяниях. Я вот например думал, что rust - это человек с такой фамилией и только, но нет, оказывается нет.

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

Ну, я тоже в работе использую разные языки. К той же жабе есть плагин hsdis который показывает код, полученый после jit. Если дизамемблировать им и посмотреть, то видно, что «лишних» команд он вставляет не на много больше чем компилятор более низкоуровневых языков на тех же конструкциях. Еще надо учесть, что когда вот так влоб сравнивают эти технологии, то надо смотреть целевую архитектуру. Когда речь идет о близких друг к другу производительностях, на разных архитектурах баланс производительности может распределиться по-разному.

Асм плох только в плане переносимости.

Ответ очевиден - юзать llvm-асм, который был задуман изначально как generic-асм.

Впрочем, С++ бывает быстрее С. Компилятор лучше встраивает шаблонные функции, чем функции по указателю ;)

Тут больше дело в том, что люди пытаются сравнить скорость фич, которые есть в плюсах с фичами которых в них нет. По сути дела, в этом уже кроется ошибка. Если же сравнивать равнозначные конструкции типа ptr->x в си и this->x в плюсах то они должны на 100% совпадать. А если сраниваем разные технологии (например юзать rtti или отключить его и завести поле с id типа), то мы получаем разную скорость этих фич даже в пределах одной программы.

Например, в вашем примере шаблонных функций и функций по указателю, вы их тоже сравниваете некорректно. Ведь когда пишут на си, то говорят - мы жертвуем временем разработки ради производительности. В соответствии с этим посылом, пишите руками десять (100, 1000, или сколько там у вас) вариантов функций на с, для каждого возможного случая, и сравнивайте уже их с шаблоном на плюсах. Вы же, сами того не осознавая, говорите - «мы не будем жертвовать временем разработки», умышленно придумываете пример в котором на си просто невозможно руками написать все за обозримое время, и получаете, по сути, результат к которому изначально стремились. Партия сказала обосновать - народ обосновал.

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

В крестах что так и не появилось возможности реализацию специализированной версию шаблона засунуть в объектный файл и выставить наружу символ для экспорта?

extern «C» ... c_fn(...) { ... tmpl_fn<...>(...) ... }.

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

... и в результате биндинги до С++ из других языков такие убогие)

Например, вот цитата из мануала по Qt Jambi («Qt Jambi is the Qt library made available to Java.»):

Binding technology -> Handling template classes

As template parameterization in C++ is a static mechanism, template classes cannot be mapped automatically to Java. The generator still handles several of the most common template classes in Qt's Tulip API. These are special cases in the generator's type system, and will map to Java's own generic container classes in the Java API.

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

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

Ответ очевиден - юзать llvm-асм, который был задуман изначально как generic-асм.

Ололо. LLVM IR платформозависимый - во первых, многие детали ABI должны на уровне IR различаться (посмотри на код, сгенеренный clang-ом для x86 и для arm-gnueabi), во вторых - явный alignment и явная упаковка структур, в третьих - платформозависимые интринсики. Нельзя LLVM IR от одной платформы скомпилировать под другую.

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

Еще и для mono и кучи чего прочего.

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

Постоянно используем C++ из С. А другие языки могут нас использовать через какой-либо другой апи, например, REST. Вообще идея выставить шаблон наружу выглядит несколько фантастической и ненужной.

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

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

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

Я придерживаюсь такой схемы — если писать на С++, то какой-то относительно весомый компонент, при этом использовать фичи С++ внутрях сколько влезет, но, при необходимости, предоставлять законченный сишный API на extern «C». Может Qt особо сложный (кстати, кто бы ещё ругал костыльность шаблонов со своими MOC :)), но если посмотреть, например, на LLVM или ZMQ, то там такая схема вполне прокатила — у LLVM есть нормальные сишные биндинги, к ZMQ через сишечку вообще из чего-угодно биндинги есть.

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

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

не автоматизируемо.

Там сверху pdf, в котором написаны жуткие цифры: лучшим в мире компиляторщикам (святым из EDG) потребовались годы на реализацию 1 ключевого слова на эту тему.

EDG’s effort:

• Design: 1.5 years (elapsed) to come up with a design they believed they could implement.

• Development: 3 person-years (3 people × >1 year each) (Note: By comparison, implementing the complete Java language from scratch took the same team 2 person-years.)

• Plus QA/testing primarily for the front end, plus their licensees’ QA/testing for complete implementations.

• EDG estimates elapsed time for other implementers approx. 2½-3 years, start to finish.

Полтора года на теорию/дизайн, 1 год на реализацию готовой теории.

Боюсь, 3,5 хипстерам из node.js до конца дней не асилить что-то подобное

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

UPD: а на практике... знаешь какое-то нибудь популярное приложение на Java с использованием гуя на Qt? SWT вижу, Swing вижу, где Qt?

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

ну сам IR независим. зависим разный платформеный обвес в виде метаданных

Метаданные-то тут при чем?!? Метаданные можно вообще безболезненно удалить без изменения семантики. Там, например, debug информация хранится.

А сам IR очень платформозависим. Те же интринсики для всех платформ разные. Alignment в IR явный.

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

у LLVM есть нормальные сишные биндинги

Они у него относительно нормальными стали к версии 3.3, и до сих пор не полностью покрывают всю основную функциональность. Раньше даже прочитать IR нельзя было через биндинги, только построить.

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

UPD: а на практике... знаешь какое-то нибудь популярное приложение на Java с использованием гуя на Qt? SWT вижу, Swing вижу, где Qt?

ты еще спроси где приложение на C# с использованием гуя на Swing, смотри в сторону PyQt, Lazarus и т.п.

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