Пользователь
0,0
рейтинг
2 октября 2013 в 16:14

Разработка → Эдвард руки — С++ перевод

Я искал, с чем бы сравнить программирование на С++ и я вспомнил фильм 1990 года режиссера Тима Бертона — «Эдвард руки-ножницы»

Это темная версия Пиноккио, снятая в атмосфере пригорода. В этом фильме жуткий парень (Джонни Депп) пытается аккуратно обнять Ванону Райден, но его неуклюжие руки-ножницы делают это очень опасным для них обоих. Его лицо уже покрыто глубокими шрамами.
Если у вас ножницы вместо рук, то это не так уж и плохо. У Эдварда много талантов: например, он может потрясающе стричь собак!
Меня часто посещают похожие мысли после посещения С++ конференций: в этот раз это было после Going Native 2013. В прошлом году были восторги и волнения по поводу нового стандарта — С++11. В этом году это было проверкой в реальных условиях. Не поймите меня неправильно: там было много потрясающих собачьих причесок (я имею в виду код на С++, который был простым и элегантным), но основная часть конференции была о том, как избежать увечий и оказать первую помощь в случае нечаянной ампутации.

Маленький магазинчик ужасов.

Там было так много разговоров о том, как не использовать С++, что это натолкнуло меня на такую мысль: речь идет не о проблеме некомпетентных программистов, просто использование С++ — это вообще неправильно. Так, если вы только изучаете основы языка и пытаетесь использовать его, то вы обречены.
У С++ есть оправдание: обратная совместимость, в частности, совместимость с С. Вы можете относиться к С как к подмножеству С++, по-настоящему ассемблерному языку, который вам лучше не использовать в повседневном программированию, кроме тех ситуаций, когда это явно необходимо. Если вы слепо погружены в С++, то вы размышляете о чистых указателях, for-циклах — всё это действительно дурацкая затея.
Хорошо известный пример того, как не надо делать — это использование malloc для динамического выделения памяти и free для ее освобождения. malloc принимает количество байт и возвращает указатель на void, который вам надо кастить во что-то более удобное — придумать худшее API для управления памяти тяжело. Вот пример действительно плохого (но почти корректного, если бы не возможность обращения по нулевому указателю) кода:
struct Pod {
int count;
int * counters;
};
int n = 10;
Pod * pod = (Pod *) malloc (sizeof Pod);
pod->count = n
pod->counters = (int *) malloc (n * sizeof(int));
...
free (pod->counters);
free (pod);

Надеюсь, что так на С++ не пишет никто, хотя я уверен, что есть много старых приложений с такими конструкциями, поэтому не надо смеяться.
С++ «решил» проблему чересчур многословного и подверженного ошибкам вычисления размера заменой malloc и free на new и delete. Корректная версия кода выше на С++ должна выглядеть так:
struct Pod {
int count;
int * counters;
};
int n = 10;
Pod * pod = new Pod;
pod->count = n;
pod->counters = new int [n];
...
delete [] pod->counters;
delete pod;

Кстати, проблема обращения по нулевому указателю тоже решилась, потому что new бросит исключение, когда системе не хватает памяти. В коде выше всё еще остается небольшой шанс утечки памяти, если второй вызов new будет неудачным (Но как часто это случается? Подсказка: насколько большим может быть n?). Короче, вот по-настоящему корректная версия кода:
class Snd { // Sophisticated New Data (в противовес POD)
public:
Snd (int n) : _count(n), _counters(new int [n]) {}
~Snd () { delete [] _counters; }
private:
int _count;
int * _counters;
};
Snd * snd = new Snd (10);
...
delete snd;

Всё ли мы сделали? Конечно нет! Код не является безопасным в плане исключений.
С++ рекомендует вам избегать чистых указателей, избегать массивов и избегать delete.
Таким образом, на замену malloc пришел оператор new, который тоже сломан: он возвращает опасный указатель, а указатели — это зло.
Все мы знаем (и шрамы на наших лицах это подтверждают), что крайне желательно использовать STL-контейнеры и умные указатели везде, где это возможно. Да, и нужно использовать value-семантику для передачи объектов. Но подождите! Value-семантика приносит потерю производительности из-за чрезмерного копирования. А что насчет shared_ptr и векторов из shared_ptr? Но они добавляют оверхэд при подсчете ссылок! Нет, вот новая идея: move-семантика и rvalue-ссылки.
Я могу продолжать снова и снова (часто я так и делаю!). Вы видите закономерность? Каждое улучшение требует нового улучшения. Теперь у нас не только С-подмножество, которое следует избегать. Каждая новая фича языка или дополнение в библиотеку порождает новую серию подводных камней. И вы знаете, новые фичи имеют ужасный дизайн, если Скот Мейерс говорил о ней. (Его последнее выступление, как вы догадались, было о подводных камнях семантики перемещения).

Философия С++


Бьерн Страустроуп подчеркивает, насколько важна обратная совместимость для С++.
Это один из столпов философии языка. Учитывая огромное количество старого кода, это имеет смысл. Но совместимость ведет к тяжелым последствиям для эволюции языка. Если бы природа относилась к обратной совместимости так же, как С++, то люди до сих пор имели бы хвосты, жабры, плавники, рога и внешние скелеты — ведь всё это имело смысл в какой-то момент эволюции.
С++ стал чрезвычайно сложным языком. Есть бесконечное множество способов сделать одно и то же — и почти все из них либо просто неправильны, опасны, неподдерживаемы либо всё вышеперечисленное. Проблема в том, что большинство кода компилируется и даже запускается. Ошибки и недочеты выявляются гораздо позже, часто после того, как продукт был выпущен.
Вы можете сказать, что это всего лишь природа программирования.
Если вы так думаете, то вам нужно как следует посмотреть в сторону Хаскеля. Ваша первая реакция будет: я не знаю, как реализовать это (что угодно, кроме факториала и чисел Фибоначчи) в этом чересчур ограниченном языке программирования. Это полностью отличается от опыта на С++, когда вы можете разрабатывать на нем с первого дня.
Вы не представляете, что в лучшем случае вам понадобится 10 лет чтобы найти «правильный путь» программирования на С++ (если он вообще есть). Представьте себе, чем лучше вы программируете на С++, тем больше функционального стиля в ваших программах. Спросите любого гуру С++ и он ответит вам: избегайте mutation, избегайте побочных эффектов, не используйте циклы, избегайте иерархий классов и наследования.
Но вам понадобится строгая дисциплина и тотальный контроль над вашими сотрудниками, чтобы это осуществить — ведь С++ разрешает всё.
Хаскель не такой добрый, он не даст вам (или вашим коллегам) писать небезопасный код.
Да, сначала вы будете чесать затылок, пытаясь реализовать на Хаскеле то, что на С++ пишете за 10 минут. Если вам повезло и вы работаете на Шона Пэрента" или других исключительных программистов, то они будут просматривать ваш код и покажут, как не писать на С++. В противном случае, вы можете быть в неведении в течение десятилетий, причиняя раны самому себе и мечтая о собачьих прическах.

Управление ресурсами


Я начал эту статью с примерами управления ресурсами (строго говоря, управления памятью), потому что это одно из моих личных предпочтений. Я выступал и писал об этом с девяностых годов (см. библиографию в конце). Очевидно, что я не справился, потому что спустя 20 лет техники управления ресурсами всё еще не общеизвестны. Бьерн Страуструп был вынужден половину свой вступительной речи говорить об управлении ресурсами перед толпой передовых С++ программистов. Опять же, можно было обвинять некомпетентных программистов в непринятии управления ресурсами как основы С++.
Однако проблема в том, что в языке нет ничего, что бы сообщило программисту о неладах в коде, который я привел в начале статьи. Фактически, изучение корректных техник принимается как изучение нового языка.
Почему это так сложно? Потому что большая часть управления ресурсами в С++ — это управление памятью. На самом деле, неоднократно подчеркивалось, что сборщик мусора не решит проблему управления ресурсами: всегда будут хэндлы файлов и окон, открытые базы данных и транзакции, итд. Всё это важные ресурсы, но управление ими скрыто тенью утомительного управления памятью. Причина, по которой С++ не имеет сборщика мусора не в том, что его нельзя сделать эффективно, а в том, что С++ сам по себе враждебен к сборке мусора. Компилятор и среда выполнения должны всегда предполагать худшее: не только что любой указатель может указывать на любой другой указатель, но и что адрес памяти может быть сохранен как целое число или его младшие биты могут быть использованы как битовые поля (вот почему для С++ рассматриваются только консервативные сборщики мусора).
Это распространенное, но ошибочное мнение, что подсчет ссылок (в частности, использование shared-указателей) лучше сборки мусора. Современные исследования показывают, что эти два подхода являются всего лишь разными сторонами одной медали. Вы должны понимать, что удаление shared-указателя может привести к сколь угодно длинным паузам в выполнении программы, равно как и работа сборщика мусора. Это происходит не только потому, что каждый серьезный алгоритм подсчета ссылок должен уметь работать с циклами, но еще и потому, что каждый раз, когда счетчик ссылок на какую-то часть данных достигает нуля, целый граф указателей, достижимых из этого объекта, должен быть пройден. Структуры данных, спроектированные с применением shared-указателей, могут требовать много времени для удаления и, за исключением простых случаев, вы никогда не знаете, какой из указателей выйдет за область видимости и вызовет деструктор.
Аккуратное управление ресурсами и использование shared_ptr всё же могут быть обоснованными в однопоточных приложениях, но вы обретаете большие неприятности, когда начинаете работать с многопоточностью. Каждое увеличение и уменьшение счетчика требует блокировки! Эта блокировка обычно реализуется с помощью атомарных переменных, но есть еще и мьютексы! Не позволяйте себя обмануть: доступ к атомарным переменным обходится дорого. Это подводит меня к центральной проблеме в С++.

Многопоточность и параллелизм


Прошло 8 лет с тех пор, как Герб Саттер лихо заявил: «Халява закончилась!»
С тех пор огромный танкер С++ всё медленнее меняет свой курс. Многопоточность не была изобретена в 2005 году. Posix-потоки были созданы в 1995 году. Майкрософт представила потоки в Windows 95, а поддержку многопроцессорных систем — в Windows NT. Однако многопоточность была признана в стандарте С++ только 2011 года.
С++ 11 был вынужден начать с глубоких раздумий. Надо было определить модель памяти: когда и в каком порядке память, записанная из нескольких потоков, становится видимой из других потоков. Исходя из практических соображений, модель памяти в С++ была скопирована с Java (за вычетом некоторых спорных гарантий, который Java дает о поведении в случае рейсов). Короче говоря, программы на С++ являются последовательно согласованными, если нет рейсов. Но С++ приходится конкурировать с языком ассемблера, поэтому полная модель памяти включает так называемую слабую атомарность, которую я предпочитаю описывать как переносимые рейсы и рекомендую держаться подальше от нее.
C++11 также определяет примитивы для создания и управления потоками, а также базовые примитивы для синхронизации, определенные Дейкстрой и Хоаром в шестидесятых, такие как мьютексы и условные переменные. Можно усомниться в том, что они являются по-настоящему верной основой для синхронизации, но это не так уж и важно, ведь их всё равно нельзя использовать в композиции. Компонуемая абстракция для синхронизации — это STM (Software Transactional Memory), которую сложно реализовать корректно и эффективно в императивном языке программирования. В Комитете Стандарта есть группа изучения STM, так что есть шанс, что в один прекрасный день STM станет частью стандарта. Но STM будет очень сложно использовать должным образом, ведь С++ не предлагает никакого контроля последствий своих действий.
Еще была ошибочная и запутанная попытка предоставить поддержку task-ориентированного параллелизма с асинхронными задачами и не компонуемыми future (и то, и другое являются серьезными кандидатами в deprecated-список в С++ 14). Локальные переменные потоков были также стандартизированы исходя из task-ориентированного подхода, который является более сложным. Блокировки и условные переменные тоже связано с потоками, а не с тасками. Поэтому это было вполне себе катастрофой. Комитет Стандарта обеспечил себя работой по удалению всего этого на много лет вперед. Работа включает в себя task-ориентированный компонуемый параллелизм, связь между потоками, чтобы заменить futures (хотелось бы надеяться), отмену task'ов и, возможно в далекой перспективе, работающий с данными параллелизм, включая поддержку GPU.
Производная от Microsoft PPL и Intel TBB должна стать частью Стандарта (надеюсь, что Microsoft AMP там не будет).
Давайте поверим в это и допустим, что все эти вещи будут стандартизированы и реализованы к, скажем, 2015 году. Даже если это вдруг случится, я всё еще не верю, что люди получат возможность использовать С++ для массового параллельного программирования. С++ был спроектирован для однопоточного проектирования, а параллельное программирование требует революционных, а не эволюционных изменений. Два слова: data race. Императивные языки не предоставляют защиты от рейсов — может быть, за исключением D.
В С++ данные по умолчанию расшарены между потоками, являются изменяемыми по умолчанию, и функции имеют побочные эффекты также по умолчанию. Все эти указатели и ссылки создают благодатную почву для рейсов, а подверженность структур данных и функций рейсам никак не отражается в системе типов. В С++, даже если у вас есть константная ссылка на объект, нет никаких гарантий, что другой поток не модифицирует его. Хуже того, любые ссылки внутри конст-объектов по умолчанию являются изменяемыми.
D, по крайней мере, имеет понятие глубокой константности и неизменности (ни один поток не может изменить неизменную структуру данных). Еще один плюс D — это возможность объявлять чистые функции. Еще в D изменяемые объекты не расшарены между потоками по умолчанию. Это шаг в верном направлении, хотя он и добавляет стоимость выполнения при работе с расшаренными объектами. Хотя самое главное: потоки не являются хорошей абстракцией для параллельного программирования, поэтому такой подход не будет работать для легковесных задачи и работой с очередями, когда задачи передаются между потоками.
Но С++ не поддерживает ничего из этого и не похоже, что когда-нибудь начнет.
Конечно, вы можете назвать всё это про-многопоточностью и фичами параллелизма как функционального программирования — в частности, неизменность и чистые функции.
Но рискну показаться навязчивым: Хаскель на голову впереди всех в отношении параллелизма, включая поддержку GPU. Вот почему я так легко перешел на сторону Хаскеля после долгих лет хорошей евангелистской практики на С++. Каждый программист, серьезно относящийся к параллелизму и многопоточности, должен изучить Хаскель, чтобы понять его работу с ними. Есть отличная книга Саймона Марлоу — «Parallel and Concurrent Programming in Haskell». После ее прочтения вы либо начнете использовать техники функционального программирования при работе с С++, либо обнаружите глобальное несоответствие между параллельным программированием и императивным языком, после чего переключитесь на Хаскель.

Заключение


Я считаю, что язык С++ и вся его философия находятся в прямом конфликте с требованиями функционального программирования. Этот конфликт несет ответственность за очень медленное внедрение параллельного программирования в мэйнстримную разработку софта. Мощности многоядерных процессоров, векторные юниты и GPU теряют производительность из-за устаревших парадигм программирования.
Библиография

Здесь я привел несколько из моих публикаций об управлении ресурсами:
  1. Bartosz Milewski, “Resource Management in C++,” Journal of Object Oriented Programming, March/April 1997, Vol. 10, No 1. p. 14-22. Здесь всё еще нет unique_ptr, поэтому я использую auto_ptr, если это необходимо. Я реализовал auto_vector, ведь нет возможности пользоваться вектором auto_ptr.
  2. C++ Report in September 1998 and February 1999 (auto_ptr еще используется).
  3. C++ in Action (still auto_ptr), Addison Wesley 2001.Смотрите часть этой книги, в которой говорится о управлении ресурсами.
  4. Walking Down Memory Lane, with Andrei Alexandrescu, CUJ October 2005 (используется unique_ptr)
  5. unique_ptr–How Unique is it?, WordPress, 2009
Перевод: Bartosz Milewski
Дмитрий @vovochkin
карма
28,0
рейтинг 0,0
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Спецпроект

Самое читаемое Разработка

Комментарии (217)

  • +25
    malloc принимает количество байт и возвращает нулевой указатель

    malloc возвращает указатель на void. void — это не NULL
    • +4
      Точно, спасибо.
  • +19
    Как много людей забывают что язык — лишь инструмент, не стоит использовать С++ потому что ты его любишь — используй там где есть от этого выгода, не стоит становиться евангелистами — вера штука опасная, знания — универсальны. Автор статьи (не перевода) был евангелистом С++, потом уверовал в новых богов и вуаля — статья готова, старые идолы повержены.

    • +7
      Ну относительно веры все очень сложно. Недостатки, которые приводит автор, у языка действительно есть. Как и есть недостатки у Хаскеля. Просто в данный момент времени человек предпочитает Хаскель, поэтому поет оды ему и говорит о проблемах плюсов. Раньше оды пелись С++, после Хаскеля придет время чего-то еще…
      А чем больше статей, тем лучше — читать их иногда интересно. Они и помогают лучше выбрать инструмент, а не верить в силу какой-то одной технологии.
      • –19
        Некорректное сравнение — у С++ есть очень большой недостаток, причем с момента его появления ,- непрозрачное управление памятью.
        • +14
          Мне кажется, что недостатки есть абсолютно у всего, в том числе и у языков программирования. Подозреваю, что Хаскель, который столь сильно восхваляет автор статьи, тоже ими обладает.
          • –23
            Не хочу спорить с адептом плюсов. Но скажу, что для своих задач я очень давно отказался от С++. Если уж все таки без него не обойтись, то пишу безо всяких плюсов на чистом Си. А, если некоторым нравится есть кактус, то это их выбор. Отладка большой программы написанной на С++ — это занятие не для слабонервных.
            • +9
              Не, я не адепт С++. Я как раз за адекватный выбор инструментов, а не за принципиальную веру в технологию или принципиальный же отказ от нее.
            • НЛО прилетело и опубликовало эту надпись здесь
            • +15
              по мне так отладка большой программы на С сложнее, с часто использующимся void*, куда запихивают все подряд, и забавными утечками памяти
              • 0
                Проблема утечек памяти легко решается использованием отладочных версий функций выделения и освобождения памяти, логирующих все эти действия с указанием, кто, когда, сколько выделил и освободил.
                • 0
                  я имею в виду большие программы, с большим количеством ветвлений, где не так просто пройти по ним всем и все отследить
                  • +1
                    Ну в общем-то и в больших все реально этим методом. Если речь не идет о миллионах строк кода.
                • 0
                  Отладочные версии malloc и free — с этим согласен. Но как вы собираетесь легко логировать действия с указателями?
                  • 0
                    в проектах изначально использую макросы вида #define X_alloc malloc, #define X_free free
                    X — какое нибудь сокращение для проекта например.
                    потом, если надо отладить утечку, заменяются макросы на #define X_alloc(size) LoggingAlloc(size, __FILE__, __LINE__)
                    пишется простенькая LoggingAlloc, логирующая например в файл переданные параметры в удобочитаемом или машинноанализируемом виде. далее утечка отлавливается без особых проблем.
                    это к слову позволяет и двойные free отладить.
                    можно еще сделать определение макросов X_alloc и X_free в зависимости от какой либо переменной препроцессора, например
                    #define DEBUG_ALLOC
                    • 0
                      Это все легко позволяет найти место в коде, в котором была выделена память. А также позволяет выяснить, что память по каким-либо причниам не была удалена, либо, как вы написали, отловить повторное удаление. Но такой подход все равно не позволяет легко выяснить, почему память не была освобождена. А это самая нужная информация. Естесственно, речь идет о действительно больших программах. Если где-то еще будет задействован механизм подсчета ссылок, то выяснить, кто удерживает ссылку еще сложнее.
                      • 0
                        На моей практике, если знать, где память была выделена — можно уже многое сказать о том, почему она не была освобождена.
                        Согласитесь, это намного лучше, чем знать, что у вас «утекло» столько то памяти.
                        • 0
                          А как вам такой вариант?
                          Я сам тоже отлавливал утечки в вебките. Я понимаю, что С++, а не С. Но почему-то мне кажется, что в С все будет только сложнее. Пример счетчиков ссылок на С — Core Foundation от Apple. В таком коде ваш метод сильно жизнь не облегчит
                          • 0
                            Ну, как я и писал, мой метод хорош для проектов среднего размера.
                            Для более крупных он уже не подойдет.
                            Мои потребности он удовлетворял =)
        • НЛО прилетело и опубликовало эту надпись здесь
          • НЛО прилетело и опубликовало эту надпись здесь
            • +6
              в java мы можем принудительно запустить GC

              Строго говоря, не можем.
              По существу, все публичные способы дергания GC в Java (вроде System.gc()) ни к чему сборщик мусора не обязывают — он может смело прогинорировать все эти просьбы даже глазом не моргнув.
            • +5
              «наверное» — ключевое слово :)
  • –36
    Полностью согласен. C++ пора на пенсию. Большинство из идиом программирования C++ не унаследованных от C не работают.

    Но, к сожалению, пока нет альтернативы.
    • +3
      Альтернативы есть. Никто же не заставляет писать именно на плюсах, если это так тяжело и неудобно?:)
    • НЛО прилетело и опубликовало эту надпись здесь
    • +47
      >Полностью согласен. C++ пора на пенсию.

      Я это слышал и 5 лет назад, и 10 лет назад, и даже 15 лет назад. Поговаривают, что и 20 лет назад говорили то же самое. Да, точно: как только Java появилась и стала более-менее распространенной, так сразу C++ начали отправлять на пенсию. Да, вы не ослышались: когда значительная часть хабраюзеров еще ходила в детский сад, уже тогда начали отправлять С++ на пенсию. А он по какой-то невероятной причине все не уходит и не уходит, несмотря на все заявления доморощенных «икспертов». Странно, не правда ли?
      • +11
        Совсем не странно. C++ — лучший вариант в соотношении скорость разработки/скорость исполнения с приоритетом скорости исполнения. В игровой (AAA) индустрии ему нет равных.
        • НЛО прилетело и опубликовало эту надпись здесь
          • +1
            Майнкрафт сделан на яве, например

            И именно поэтому там всё очень удачно в плане модификаций и плагинов.

            У каждого языка есть свои недостатки и плюсы, для разных целей — разный инструмент.
            • 0
              Удачно только лишь потому, что удалось декомпилировать его. Если сравнить написание модификаций на движке Source и Minecraft, второе — сущий ад. Конечно, отчасти потому, что api никакого нет. Но на плюсах «копошить» внутренности куда удобнее и практичнее. Я уж не говорю, какую нагрузку они дают на и так очень тяжелую игру.
              • 0
                Не могу сказать что моддил Source, а вот в minecraft копался. Исходного API не очень много, но при добавлении forge — хватает.
                P.S. Про нагрузку вы верно подметили — просто огромная.
          • –1
            Выставьте Render distance хотя бы в 512 блоков, тогда узнаете как майнкрафт не тормозит. И это после обработки OptiFine-ом.
            • НЛО прилетело и опубликовало эту надпись здесь
  • +16
    Я считаю, что язык С++ и вся его философия находятся в прямом конфликте с требованиями функционального программирования.


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

    Конечно, идея смотреть на функциональные языки в контексте многопоточности — здравая. Могу подтвердить, правда, не Хаскеллем, а Эрлангом — после полугода программирования исключительно на нем, код на плюсах тоже стал намного более функциональнообразным со всеми приятными бонусами в виде потокобезопасности и читаемости.

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

    При этом С++ движется и в сторону параллельного программирования, хотя и не всегда так здорово, как хотелось бы. PPL и AMP, например, как раз и предназначены для задействования многоядерных платформ и GPU. Все мы там будем. Хотя и не сразу. Хотя, наверное, и не все.
    • 0
      Да, у Мейерса, кажется, было целое правило про мультипарадигменность С++ — каждый волен выбирать свой подход.
      • +3
        И у этого тоже есть своя обратная сторона. На С++ нельзя в колхоз.
    • НЛО прилетело и опубликовало эту надпись здесь
      • +3
        Имеем функцию, принимаем объект константно по значению, создаем новый объект в контексте, делаем с ним все что угодно, возвращем по значению (кстати, перемещение тут работает норм). GC не нужен.

        В принципе мы можем вообще не создать ни одного объекта вне контекста той или иной функции.
        • НЛО прилетело и опубликовало эту надпись здесь
    • 0
      Неловко из-за своего незнания, но что используется в ФП в качестве эквивалента циклам?
      • +1
        Например, map. Функция, которая применяет функцию к каждому элементу чего-либо. Как for-each. Разницы на самом деле немного. В Питоне, например, циклы сделаны в императивном стиле, но фактически работают над ленивыми списками.

        Ну и классика — рекурсия. В теле функции проверям: если счетчик дошел до конца, ничего не делаем, если нет — делаем что-то, запускаем саму же функцию с подвинутым счетчиком. Сперва выглядит неуклюже, но это дело привычки.
        • 0
          На счет map, получается действительно не координатная разница. А на счет рекурсии, как замены циклам, я как-то подзабыл :)
          • +3
            Простите, не координатная? ;)
            • +3
              Думается нам всем пора спать :)
              • 0
                2 октября 2013 в 18:12 по Москве. 19:12 по Ташкенту. Рановато спать.
                • +1
                  Универ творит чудеса.
  • +9
    Нужно наконец заняться выпиливанием deprecated хлама и делать это активнее. Хотя это же и Си касается. А заодно и выкинуть из железа и осей кучу deprecated мусора надо бы. Но видимо нам еще долго придется жить с рудиментами.

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

    Справедливости ради, после даже беглого изучения Хаскеля начинаешь куда лучше писать и читать С++ шаблоны.
    • +3
      deprecated хлам часто выпиливают в отдельных конторах — жесткие codestyle'ы, ревью плохого кода просто не проходит. А из языка все рудименты убрать не так-то просто: обратная совместимость тянет такие идеи ко дну.
      • +1
        Так ведь сколько этих рудиментов в процессорах осталось к примеру.
        • 0
          О да, особенно в x86 ^^'
      • 0
        Обратная совместимость это то, что не нужно новым проектам написанным с нуля, и большинству библиотек относительно свежих версий.
      • +3
        Интересно, а никому в голову не приходило выпилить все рудименты и просто назвать язык по новому? Какой-нибудь CleanC++, тогда и с обратной совместимостью проблем нет, так как это, по сути, новый язык. И с каждым апдейтом С++ добавлять фичи и в CleanC++
        • +4
          А кому он нужен будет?
          • 0
            Как писали выше, для «отдельных контор», да и коммент пользователя Gorthauer87 плюсанули уже 9 раз, значит это как бы востребовано. Ну и, лично мне кажется, что язык, из которого вырежут всё устаревшее, станет только лучше, разве не так?
            • +4
              Если переписать все 100500 библиотек и фреймворков.
          • +1
            Сделать его бинарно совместимым на уровне объектных файлов с «обычным» C++. По сути это флаг компилятора, выключающий вещи, которые нельзя использовать в исходнике.
    • +1
      Насчет замены — посмотри на Golang. Мне после Go на C и C++ возвращаться не хочется. ;-)
      Rust — интересный (и похож во многом на Go), но пока еще не готов для продакшн.
      • 0
        Про go забыл, хотел его написать. Там вроде бы многопоточность сделана более менее удачно.
  • НЛО прилетело и опубликовало эту надпись здесь
    • +7
      Ну судя по всему, он и плюсами упарывался неслабо, так что ему можно:)
  • +1
    Ну, отлично. А, допустим, мне нужно выделить память для пяти объектов, размеры которых мне известны заранее? И, допустим, объекты нужны все целиком, или ни один из них.

    Я могу сделать malloc на сумму размера, и выделить потом указатели на эту штуку. Да, не очень красиво. Но мы экономим память, у нас нет дифрагментации кучи, и, может, даже из-за кэширования чуть чуть выигрываем в производительности.

    А теперь мне надо сделать пять раз new?

    Кроме этого, я работаю под SSE, и мне надо сделать aligned malloc. Ладно, скажут, расслабся — у нас всегда aligned malloc, это, правда, в стандарте не прописано — но вы просто поверьте, а поймёте потом?

    Или по той или иной причине хочу выровнять malloc на ширину кэш линии. Ну, межпроцессорные взаимодействия, то, сё.
    • НЛО прилетело и опубликовало эту надпись здесь
      • 0
        Почему? У меня есть пять запросов на выделение памяти с каким-то размерами. Почему это будет работать не хуже, чем один такой запрос?

        Это может определить только компилятор: ооо, мы тут выделяем все вместе, а тут освобождаем все вместе, давайте заменим это на одну операцию.
        • НЛО прилетело и опубликовало эту надпись здесь
          • 0
            Т.е. код

            int* b[1000] for(int i=0; i<1000; i++) { int* a = new int[256*1024*1024+i]; b[i] = new int; // do something free(a) }

            Убьёт всё, как только вылезем за адресное пространство процесса? Атлично-атлично!
            • НЛО прилетело и опубликовало эту надпись здесь
              • 0
                Не-не, я не про производительность, а про дефрагментацию. Мы же free(b[i]) не делаем!

                Получается, скушали кусище, скушали кусочек, освободили кусище — так несколько раз — и оп.
                • НЛО прилетело и опубликовало эту надпись здесь
            • НЛО прилетело и опубликовало эту надпись здесь
    • 0
      Вообще-то для этого есть массивы. Один new для массива из 5 объектов сделает все, что нужно, учитывая выравнивание и без фрагментации.
      • 0
        Да лучше просто вектор объявить. А все выделения памяти, распараллеливание и т.д. автоматом уйдут на сторону стандартной библиотеки.
        • +1
          Хорошая иллюстрация неправильного использования возможностей С++.
          Вектор это массив позволяющий динамически изменять размер. В условиях было фиксированное количество объектов, то есть вектор тут, во-первых, явный оверхед, а, во-вторых, прекрасный шанс выстрелить себе в ногу, изменив таки его размер, что может вызвать перевыделение массива, и обратившись к объекту по старому указателю.
          • +2
            Хорошая иллюстрация не самого вдумчивого чтения тз.
            В условиях сказано, что _размер_ объектов заранее известен. Их количество тоже упомянуто, но про неизменность этого числа не сказано ничего! Это во-первых.
            А во-вторых — какое «обратившись по старому указателю»? Тут «выстрел в ногу», а точнее «заряжание ружья» произойдёт ранее, а именно в тот момент, когда вместо итератора вдруг (откуда?) всплывёт указатель.
            А что касается изначальной задачи — размещение (где-то) нужного количества элементов — то она как раз будет выполнена. И детали этого процесса могут оказаться гораздо сложнее, чем банальный new или даже malloc
            (доводилось работать с реализацией, где вектор держал небольшой буфер на несколько десятков байт прямо у себя, а для большего вообще сразу лез в систему, выделяя себе страницу с помощью апишного VirtualAlloc. И, надо сказать, обгонял при этом и new и даже malloc)
            • +1
              > Хорошая иллюстрация не самого вдумчивого чтения тз.
              > В условиях сказано, что _размер_ объектов заранее известен. Их количество
              > тоже упомянуто, но про неизменность этого числа не сказано ничего!

              Это следует из дальнейшего описания. Смысл поста в том, что если понадобилось несколько (допустим 5) однотипных объектов, то вместо пяти вызовов new выгоднее один раз вызвать malloc на все пять, создать указатели (база+смещение) на них и работать с каждым из них по отдельности. Никаких итераторов не предполагается, так как это просто отдельные пять объектов.

              > Я могу сделать malloc на сумму размера, и выделить потом указатели на эту штуку.

              Так вот, выделение массива из 5 объектов решает ту же задачу, избавляя от низкоуровневой возни с malloc, выравниванием и т.д.

              При этом вектор эту задачу не решает или решает плохо. Как я и писал, если не изменять размер — оверхед, если изменять — повисшие указатели стреляют по ногам.

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

    Что, простите?
    • НЛО прилетело и опубликовало эту надпись здесь
      • 0
        Я бы еще пропустил утверждение, что атомарные операции на int'е — это дорогая операция (это говорит апологет GC, муахаха). Но при чем тут мьютекс?!
        • НЛО прилетело и опубликовало эту надпись здесь
          • +1
            Так я и говорю, что само по себе утверждение про дороговизну атомарных операций на int можно отстаивать, но когда рядом с shared_ptr выплывает мьютекс — это похоже на подтасовку, собственно как и вся статья в целом.
  • +7
    Извините конечно, но очень уж стремно выглядит перевод (?) race как «рейс»
    • +3
      В русском язык мне не известен адекватный перевод термина «data race». Мне привычен разговорный вариант, который часто используется в программистских кругах (или я часто его слышу) — «рейс», его и использовал. И да: вы не первый, кто мне указывает на «корявый» перевод этого термина, но я все же настою на своем варианте.
      • +2
        Мне казалось, вполне устоялся перевод как: «гонки данных», «состояние гонки».
        • 0
          «Состояние гонки» — это всё же race condition, немного другое то есть.
          «Гонки данных» — скорее уж, гонки за данными.
          Singerofthefall предложил еще и термины «конкуренция данных» или «конкуренция потоков», но мне почему-то всё это не нравится. Возможно, дело привычки.
          • –2
            Как вариант — коллизия данных?
            • +2
              Этот термин мне не нравится из-за своей распространенности в теории баз данных.
              Я ни в коем случае не нахожу отговорки для отказа от предлагаемых мне вариантов, просто все эти причины мне и правда кажутся объективными:)
          • +3
            Просто «гонки». Отлично подходит для всех случаев в статье. Рейс режет глаз.
      • 0
        Хотя бы «рэйс».
  • +1
    C++ монструеет, из него пытаются сделать швейцарский нож на все случаи жизни, при этом теряется главная киллер-фича: эффективная компиляция. Не нужен ещё один скриптовый язык, ещё один функциональный, ещё один многопоточный. Нужен язык для (1) эффективной компиляции (2) сложных архитектурных решений.

    Многопоточность — вещь конечно же нужная, но не в виде же костылей! Через несколько лет в десктопах будут стопицот-ядерные камни, и программисты свихнутся распараллеливать на них в мьютексной парадигме, потому что мьютексы (и семафоры) — это тупиковая модель. Откройте для себя Erlang с message-парадигмой, почувствуйте разницу!

    И не понял упрека shared_ptr на счет релиза дерева ссылок — раньше это приходилось делать «ручками» явно, теперь это делает shared_ptr. Главное — момент сборки детерминирован самим программистом, а не размазан на «когда нибудь» как в Java GC.

    Оставьте плюсам — плюсово, а последние достижения языкознания и компиляторостроения примените к перспективному D.
    • НЛО прилетело и опубликовало эту надпись здесь
    • 0
      Главное — момент сборки детерминирован самим программистом, а не размазан на «когда нибудь» как в Java GC.
      Вот в этом и есть ваша ошибка

      //management thread
      std::shared_ptr<int> ptr;
          
      //worker thread
      std::weak_ptr<int> wp = ptr;
      std::shared_ptr<int> ptr2 = wp.lock();
      


      Вы можете предполагать (по логике), что ptr должен (долго) удаляться в management thread, и это нормально. Но worker thread не должен тормозиться на удалении ptr. Однако, на самом деле, если management thread завершится до освобождения ptr2, указатель будет (долго) удаляться в worker thread.
      • +1
        Согласен, но по тексту статьи — обход дерева при освобождении shared_ptr упоминался именно в контексте управления памятью/ресурсами. Про shared_ptr в многопоточности автор потом отдельно упомянул, что вы «обретаете большие неприятности», что опять же подверждает мой посыл — поддержка многопоточности в плюсах идет не туда.
  • +1
    Фееричная статья. Шикарная и провоцирующая аналогия вначале, детальный разнос в тексте и слегка предраспологающее к холиварам заключение :)

    Замены назревают сами собой, так что не Хаскеллем единым. Для ориентированности на работу с concurrency языкам не обязательно быть функциональными, равно как и для удобства разработки больших проектов, язык не обязательно должен быть классическим ООП-языком.
    Из самых зрелых, мощных и с хорошей кармой, пока что ИМХО это Golang — у него очень низкий порог входа из-за большой схожести с С. И после Go возвращаться на C/C++ уже не хочется.

    На горизонте еще маячит Rust — близко не знаком, но выглядит очень симпатично.
  • +3
    Я, конечно, не знаю, но так тоже никто уже не пишет на С++
    Snd * snd = new Snd (10);
    ...
    delete snd;


    Автор несколько устарел, отсюда и делает неправильные выводы. Правильно писать так:
    std::unique_ptr<Snd> snd(new Snd(10));


    Более того, Snd тоже неправильно реализован. Там тоже надо использовать умные указатели. Т.к. unique_ptr не использует атомарные операции, то также неправильный вывод о том, что будут проблемы в многопоточных средах.

    Каждое увеличение и уменьшение счетчика требует блокировки! Эта блокировка обычна реализуется с помощью атомарных переменных, но есть еще и мьютексы! Не позволяйте себя обмануть: доступ к атомарным переменным обходится дорого.
    Кручу, верчу, обмануть хочу. Сначала говорится про блокировки, потом про атомарность, потом про мьютексы и опять блокировки. Так это, нужны блокировки для счетчиков или нет? Тумана много напустили. И да, обмануть мы себя не позволим: при отсутствии большой конкуренции к атомарным счетчикам такая операция стоит очень дешево. И не надо лохматить бабушку!
    • 0
      Т.к. unique_ptr не использует атомарные операции, то также неправильный вывод о том, что будут проблемы в многопоточных средах.
      Как использовать unique_ptr в многопоточных средах?
      • +2
        По разному. Можно — используя атомарные конструкции, можно через мьютексы. Тут стоит обратить внимание не на то, что надо об этом думать, а о том, что автор статьи утверждает, что «доступ к атомарным переменным обходится дорого», поэтому (это уже от меня), дескать, shared_ptr не стоит использовать. Я же говорю, что можно использовать, во-первых, unique_ptr, во-вторых, можно использовать мьютексы, и даже нужно там, где они необходимы.

        Автор также говорит про D, типа там есть чистые функции и константные объекты, поэтому есть некие гарантии. Однако, мне не очень понятно, как на D можно работать, на пример, с глобальными контейнерами типа hash_map со всеми ихними константностями и чистыми функциями. Кто-нибудь мне это объяснит? Более того, на С++ тоже можно творить чудеса, см. Полезные идиомы многопоточности С++. В ней я описал, как можно использовать объекты без всяких локов из разных потоках.

        Поэтому пафоса автора статья я категорически не разделяю. Указанные примеры кода говорят о том, что автор не знает языка (или знает на достаточно примитивном уровне), и лишь «красиво» треплет языком по делу и без обо всем.

        Да, язык С++ не без изъяна, он тяжел для обучения и достаточно громоздок. Но тем не менее, его рано списывать со счетов. Тем более, используя феерические аргументы.
  • +12
    … Использовать ножи на кухне — это вообще неправильно! Речь даже не о том, что ты можешь порезаться — я верю, что после должного тщательного обучения настоящий профессионал сможет достаточно безопасно приготовить бутерброд. Ведь оставленный на столе нож может привести как к травме (порежется кто-то другой, недостаточно опытный или подготовленный), но и преступлению — оставленные без присмотра ножи могут быть использованы злоумышленниками! А прцесс заточки ножей? Сложность и опасность его неоспоримы. И это в то время, когда любой человек совершенно спокойно может купить порционные продукты — в гигиеничной индивидуальной упаковке, не требующие нарезки! Да, есть стейк без ножа очень неудобно, но ведь прогресс дал нам мясорубки, а котлетки ничуть не менее вкусны и куда более современны, чем эти дикарские стейки! Зачем пытаться как-то совершенствовать безнадежно устаревшую концепцию, придумывая ножи из керамики, самозатачивающиеся, одноразовые ножи из пластика и т. п.? Ведь очевидно, что человечество в ближайшем будущем перейдет на прогрессивное питание полужидкой пастой из тюбиков! Заметьте, что эта передовая технология успешно опробована в космосе, где нет места эти артефактам каменного века — ножам!
    • НЛО прилетело и опубликовало эту надпись здесь
      • +4
        Не могу с вами согласиться, увы. С++ — это именно обычный стальной нож. Достаточно опасный, но при этом универсальный и крайне полезный инструмент даже на самой современной кухне. А так — да, полно всяких кухонных комбайнов, блендеров и прочих ломтерезок, конечно.
        • НЛО прилетело и опубликовало эту надпись здесь
          • +2
            Автор статьи исходит из ложной предпосылки, что malloc/free или new/delete — это абсолютное зло. А на самом деле это просто возможность порезаться.
            Ну нет задачи исключить любую потенциальную угрозу от ножа — иначе им резать же не получится.
            • НЛО прилетело и опубликовало эту надпись здесь
              • +1
                Да это на здоровье. Никто же не спорит, что ножом суп есть неудобно. Однако популярность супа — не повод демонстративного отказа от ножей в пользу ложек.
                • НЛО прилетело и опубликовало эту надпись здесь
        • +3
          На сой взгляд не совсем точная аналогия. Обычный стально нож это C. А потом решили его улучшить и чтобы не терять совместимость, сделали у ножа второе лезвие — получится обоюдоострый. Новое лизкие — C++, старое — C. Резать можно и тем и тем, можно даже чередовать.
          Потом изначальный нож стал развиваться дальше потихоньку, но на новом старое лезвие заморозило свое развитие.
          С новым еще интереснее. Подумали, что не удобно им резать неторые продукты. Да и порезаться можно… В итоге каждая версия стандарта добавляет на этом лезвии новый участок с хитрой формой и заточкой, при этом старась не строгать уже имеющиеся — люди же уже привыкли ими резать.
          И резать таким ножом становится все сложнее. Даже для распространенных продуктов имеется не одно лезвие, а несколько. Причем часть из которых объявлено устаревшими, но они все еще острые и о них можно порезаться.
          В общем инструкция к ножу уже перевалила за 100 страниц, и чтобы его освоить уже нужно годичные курсы закончить(просто чтобы не резаться по 5 раз в день), притом что нож позиционируется как массовый и продается на каждом углу.
  • НЛО прилетело и опубликовало эту надпись здесь
  • +2
    Я считаю, что язык С++ и вся его философия находятся в прямом конфликте с требованиями функционального программирования.
    — конечно, ведь С++ не функциональный язык

    устаревших парадигм программирования
    — устаревших парадигм не бывает

    Вы считаете ручное управление памятью и потоками в С/С++ недостатками? По-моему, это как раз и является сутью и одновременно мощью С/С++. Всё, что можно сделать на других языках программирования можно сделать эффективнее на С, поскольку С — это практически взаимно однозначное соответствие ассемблеру, а какими бы не были эти ваши языки, исполняются они не на этих ваших квантовых компьютерах, а на вполне обычных процессорах.

    А если кто-то не умеет программировать на С/С++, то это его проблемы.

    • НЛО прилетело и опубликовало эту надпись здесь
      • +3
        Пока компиляторы ваших Java и Haskell пишутся на С, то и говорить не о чем.
        • НЛО прилетело и опубликовало эту надпись здесь
          • +1
            Быстрота Haskell обеспечена тем, что программисты С реализовали своё управление памятью, свою многопоточность для решения конкретной задачи. Иначе бы ваш Haskell загнулся бы и работал бы со скоростью runhaskell.
            • НЛО прилетело и опубликовало эту надпись здесь
              • –1
                Я бы сказал так. На С++ надо смотреть как на С с дополнительным typedef-ом структуры в виде класса. Тогда будет всем понимание и красота программирования.
        • НЛО прилетело и опубликовало эту надпись здесь
          • +1
            Речь идёт о JVM. Если бы JAVA исполняла JAVA, то всё бы, вообще, загнулось и не работало.
            • НЛО прилетело и опубликовало эту надпись здесь
              • 0
                Почему же тогда JIT пишут всегда только на С? Правильно, тут требуется работа с памятью напрямую, на что эти ваши языки не способны. Вообще, все языки написаны на C/C++ (иначе выходит колоссальный ущерб производительности). Даже сам С/С++ написан на себе же. Поэтому — это единственный замкнутый и нормальный язык программирования.
                • +3
                  К тому же С — это и есть единственный истинно платформонезависимый язык, ибо первое, что реализуется на любой платформе — это компилятор С, а за ним уже всякие ОС и т.д.
                  • НЛО прилетело и опубликовало эту надпись здесь
                    • +2
                      Ассемблер — это мнемоническая запись команд процессора. Первым реализуется перевод кода на С в байты ассемблера, тобишь что является самим компилятором С.
                      • +1
                        Современные ассемблеры это нечто большее чем мнемоническая запись команд.
                      • НЛО прилетело и опубликовало эту надпись здесь
                • НЛО прилетело и опубликовало эту надпись здесь
                  • –1
                    Языков среднего уровня всего две штуки — это С и С++.
                    • НЛО прилетело и опубликовало эту надпись здесь
                      • 0
                        В таких случаях принято приводить примеры, тем более, что вас о них спросят в первом же ответе. Так почему бы не сэкономить всем немного времени?
                        • НЛО прилетело и опубликовало эту надпись здесь
                    • 0
                      Взять паскаль/дельфи. Модель памяти та же самая, синтаксис только чуть другой и функции называются по-другому.
                • +4
                  Вообще, все языки написаны на C/C++ (иначе выходит колоссальный ущерб производительности).

                  Господи, что за бред?

                  Про Модулу, например, не слышали?
                  Или про другие низкоуровневые языки?

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

                  Как пример, Java тоже получил широкую популярность в Enterprise среде, а PHP в web-разработке. Но оба этих языка страдают кучей врожденных проблем, которые потом решались путем создания новых языков (Python, Ruby, Scala и прочие).

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

                  Отсюда при использовании С/С++ возникает куча правил, как стоит и как не стоит писать, которые построены после десятков лет дебаггинга неуловимых багов.
                  Куча правил, стандартов, условностей, из-за тупо устаревшего концептульано языка, который пытаются возродить новыми стандартами, в то время как правильнее переходить на или разрабатывать более современные низкоуровневые языке (по аналогии того, как, например, была создана Scala, как ответ на несовершенство и медленное развитие Java)
        • +4
          Пока компиляторы ваших Java и Haskell пишутся на С

          Почти весь компилятор Haskell написан на (literate) haskell: https://github.com/ghc/ghc. Сишного кода там довольно мало. Тем не менее, используются некоторые динамические библиотеки, написанные на C, вроде libgmp
  • +1
    Почему-то, когда в процессе написания игры, ко мне кто-то подходит и спрашивает на чем я пишу, а я отвечаю, что на C++, то это вызывает у людей смех. Этот мир уже не спасти?
    • +3
      Я тут же сразу вспоминаю Minecraft и Battlefield 2. В Battlefield 2 почему-то я на своём компе играть могу, а в Minecraft нет…
      • 0
        Во-во. Я обычно в пример привожу торрент-клиент Azureus (он же Vuze), написанный на Java. Он мега удобный, но на старом лептопе с 2 гигами памяти, он выжирал ее всю.
        А уж в играх, где производительность критична, это и подавно актуально.
        • +1
          Просто более-менее крупный проект писать на только одном языке — недальновидно. Я лично для себя нашел идеальную связку: Java для управляющего высокоуровневого кода — манипулирование объектами бизнес-логики, пользовательский интерфейс, машины состояний, то есть то, что Java хорошо умеет, для чего она и делалась. Если между двумя командами проходит более одной миллисекунды машинного времени (я утрирую, конечно), производительность не важна.

          А для низкоуровневых алгоритмических задач типа обработки изображений, «перепахивания» крупных массивов данных, рисования графики на OpenGL — язык Си. Да-да, даже не C++. Я использую компилятор C++, чтобы вместо неуклюжих malloc и free иметь new и delete, а также задействовать исключения. А функции вызываются из Java через JNI. Крупные данные хранятся в обычной памяти, всякая разномастная мелочь типа состояний объектов — в Java-памяти.

          Вот такой «гибрид». Всем рекомендую. При использовании gcc toolchain и Eclipse с установленными плагинами JDT и CDT можно даже сквозную отладку осуществлять. Главное достоинство — производительность кода на Си в «острых» местах и удобство Java с ее сборщиком мусора и шикарным отладчиком — во всех остальных.

          Если бы, например, Minecraft не использовал LWGL для отрисовки всего и вся, а имел бы собственный GL-биндинг на Си, вы бы не отличили производительность
          • 0
            Мудро. Я использую связку QML + JS + C++.
  • +5
    Слышали поговорку: «Не умеешь, не берись»? То, что вы считаете недостатками, я считаю огромными плюсами языка (ручное управление памятью или статическая типизация, например) и использую его только ради них (ну еще за компиляцию в бинарный код). И уж сколько мне не будут доказывать преимущества GC, он все равно никогда не сможет работать с памятью лучше, чем я. Ибо кому, как не программисту, лучше знать, когда область памяти больше не нужна и ее стоит очистить?
    • +2
      >Ибо кому, как не программисту, лучше знать, когда область памяти больше не нужна и ее стоит очистить?

      Зависит от программиста. Бывают такие, к которым лучше приставить няньку в виде GC. И их, к сожалению, слишком много.
      • –5
        Это не программисты, а быдлокодеры
        • +5
          Других ругать — себя хвалить
      • 0
        А почему из-за таких индивидов должен страдать конечный пользователь? Если со всеми нянчится, то дела никакого не будет. Лучше уж дать флаг в руки естественному отбору и пусть эволюция делает свое дело — плохие кодеры будут увольняться, а те, кто научится, будут писать нормальный софт. А там гляди и зарплаты побольше станут.
        • +4
          Улыбнуло :) Вы так говорите, как будто злые быдлокодеры захватили власть в IT и диктуют всем свои условия :)

          Хотите я вам озвучу логику менеджмента софтверной компании?
          Я лучше найму 10 джавакодеров, которые понятия не имеют, что, как и когда удаляется, но они за 3 месяца напишут продукт, который я начну продавать и заработаю деньги, чем я за те же деньги найму 5 мега-сишников, которые просто ппц какие умные, но писать тот же самый продукт они будут год (просто потому, что во-первых их вдвое меньше, а во-вторых разработка на джаве идет реально быстрее, чем на Си), а за это время мой продукт уже будет на хрен никому не нужен, т.к. конкурент выпустит свой аналог через 3 месяца и захватит весь рынок, в результате чего мне придется закрыться к чертям и идти собирать бутылки.

          Конечные пользователи не страдают. Конечные пользователи задают этот тренд, молчаливо покупая и используя говнософт.
          • +1
            Перефразируя предыдущего оратора чуть общее: в любой области, где человечество что-либо создаёт, от живописи до производства автомобилей, сперва появляются несколько гениев, которые намечают основной тренд, потом творчество обретает популярность, становится выгодным и появляется рынок труда для «ремесленников», причем выигрывают не те, кто делает лучше, а те, кто лучше продаёт готовый продукт.

            Так что «пипл хавает». Зарабатывают больше всех середнячки, нашедшие баланс между качеством и ценой. И это — закон природы, на который непродуктивно обижаться.

            Утешает только то, что количество гениев по абсолютному значению не меняется. И хотя их слышно хуже, когда вокруг такой «гвалт», они продолжают создавать шедевры. Надо лишь уметь их видеть.
  • +5
    На самом деле Erlang, Haskell и вообще функциональное программирвоание — отличные штуки. Особено когда все бесконечно параллелится и у вас есть кластер, на котором можно все это дело запускать и быстро добавить туда еще машин, когда понадобится.

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

    Реализовать же пересылку событий между потоками, как в Erlang, в С++ не представляет какой-то проблемы.

    Про мьютексы и атомарные переменные — вообще не серьезно. Автор, наверное, думает, что функциональные языки используют внутре себя какую-нибудь магию для организации подсчета ссылок и синхронизации между потоками, но уж никак не примитивы ОС и атомарные операции. Или логика такая — раз я мьютекса не вижу — занчит его нет?
    • +4
      Логика такая, что

      1. multi-threading approach — Semaphores, Threads, Shared Memory
      2. message passing approach — Queues, Messages, Processes
      3. data flow concurrency
      4. software transnational memory

      Это все разные модели parallel/concurrency вычислений. Операционные системы поддерживают только первый вид. Остальные модели реализуются посредством библиотек и собственных планировщиков легковесных потоков со своими стеками работающих в контексте одного потока ОС.

      Чисто логически представьте себе что в одном 32-битном потоке Эрланга работает 1 000 000 процессов, откуда там столько примитивов ОС.
      • 0
        Внутри одного потока ОС синхронизаиця, конечно, не нужна. Но если мы хотим использовать более одного потока ОС, да и вообще взаимодействоать с внешним миром, то нашему планировщику придется использовать какие-то механизмы синхронизации. Сколько бы библиотек мы не использовали, в итоге все равно все сводится к примитивам ОС или атомарным переменным. И как только мы хотим перейти через границу своего уютненького потока, нам их приходится использовать.
        • 0
          1 000 000 процессов. 32 бита. Подумай еще раз, возьми калькулятор и пересчитай.
          • +1
            1 000 000 легких процессов, которые работают по очереди (точнее, 999 990 из них спит)? И что? Я же говорю про параллельные вычисления, а не про concurrecny.
    • +1
      Как обычно бывает в таких случаях, войну между императивными и функциональными языками выиграет язык, который умудрится помирить обе парадигмы внутри себя.

      За примером подобной победы далеко ходить не нужно. Обсуждаемый здесь C++ в своё время победил в споре между C и объектно-ориентированным Smalltalk-ом, включив в себя ООП вида «объект-тип данных», который отлично уживался со стилем программирования на тогдашних императивных языках, популярен до сих пор и, по сути, мирит между две парадигмы между собой.
      • 0
        Так есть же языки, которые на это претендуют. Ruby, например, или F#.
        • 0
          Сузим круг. Язык должен иметь C-образный синтаксис, чтобы 80% разработчиков, пишущие на C/C++/Java/Javascript не меняли своих эстетических предпочтений (то есть, например, не F#, а C# хотя бы) и, кроме того, он должен быть независимым, то есть иметь лёгкую (хотя бы как stdlib/stdc++) стандартную библиотеку, не тянуть за собой виртуальную машину и по производительности результата соперничать с Си.

          Я бы сказал, язык, похожий на C# (но с более развитой функциональной семантикой) с компилятором, написанным на основе LLVM (как вариант).
          • +2
            Проблема в том, что С-подобный синтаксис не очень-то подходит для программирования в функицональном стиле. Некоторых конструкций просто нет в С стиле (паттерн матчинг, гуарды), дургие имеют зубодробительный синтаксис (оперирование функциями высших порядков, частичное применение, каррирование)
            • +1
              Я думаю, что проблема еще глубже. Разглядывание программ на функциональных языках (писать на них пока не умею, только читать пытаюсь немного) привело меня к мысли, что обычная, привычная нам запись в виде последовательного текста вообще для них не годится. Удобнее бы выглядела графическая блок-схема. Причем такие языки уже есть — навскидку два самых популярных — LabView для математики и SynthMaker для оперирования со звуком (создание VST и VSTi). При этом ничто не мешает добавлять в функциональную блок-схему «островки» императивного кода, который, в свою очередь, лучше выглядит в виде текста.

              И, кстати, посмотрев на то, как с кодом и связями работают современные IDE (я в данном случае имею в виду, например, графические связи в XCode 4), можно представить себе, к чему всё идет…
              • 0
                Инфраструктура (системы контроля версий, например) заточены под текстовые исходники.
                Можно сохранять диаграммы в XML, но (судя по тому, как это сделано в MS Reporting Services и Analysis Services), глазами быстро понять суть изменения по diff-файлу очень сложно.
                • 0
                  Вопрос привычки. По чистому diff-файлу понять изменения тоже непросто — нужна удобная программа визуализации. А то, что структурированные данные мозг лучше принимает, чем колонку текста или цифр — общеизвестный факт. И первые шаги уже делаются — например все среды разработки сейчас поддерживают автоматическую и удобную для человека индентацию.
                • 0
                  diff в случае графического языка выглядит чуть иначе. Вот как это выглядит в LabVIEW в простейшем случае:
                  image
                  Код мы храним в MS SourceSafe, при просмотре различий вызывается специальная утилита. Мержить такой код тоже можно (но нам это очень редко приходится делать).
                  • 0
                    Уточню, о чём я хотел сказать. Очевидное визуальное изменение (врезка в середину диаграммы нового объекта со сдвигом всей нижележащей диаграммы вниз) повлечёт большую цепь изменений в сериализованном в файл представлении (если там координаты объектов сохранены). Конечно, современные VCS съедят мегабайтные диффы и не подавятся, а внешние тулзы визуализируют разницу двух версий, но как-то это неправильно. Если кто-то вставит в диаграмму объект в другом месте и тоже со сдвигом остатка вниз, мержить это будет просто невозможно.
                    • 0
                      Там (в LabVIEW) всё чуть сложнее. Есть понятие Data Flow («потока данных»), и если диаграмма просто раздвигается для вставки новых элементов — это считается «косметическим» изменением и не приводит к изменению Data Flow. Если два разработчика вставили по куску кода (не конфликтующего), раздвинув оригинальную диаграмму в разных направлениях, то такой код прекрасно мержится, так как вначале меняется Data Flow, а потом результирующая диаграмма раздвигается в обоих направлениях (ну при больших изменениях, возможно придётся ручками кое-что подвигать). Могу скриншот сделать, если интересно. В настоящее время, конечно неудобно то, что в системе контроля версий файлы хранятся как двоичные и об их содержимом SCC ни сном ни духом. Сериализация как таковая в LabVIEW вообще не предусмотрена, соответственно диффов тоже нет (ну разве что визуально показывается что там куда мержится — примерно как на скриншоте выше). Вообще формат исходников LabVIEW — суть внутренний закрытый формат (что конечно, не есть хорошо). Возможно в будущем появятся похожие средства графической разработки с открытым форматом и соответственным образом заточенные под них системы контроля версий.
                      • 0
                        Понятно, но у такого подхода есть и минус: если пользователь переместит элементы, чтобы придать схеме красоты (код же равняют отступами), то система это не сохранит.
                        • 0
                          Сохранит — эта информация тоже ведь хранится в исходном файле. Но для системы контроля версий, конечно не будет разницы — просто косметическое изменение сделано или принципиальное — в настоящее время система видит лишь изменившийся двоичный файл. О деталях изменений знают только внешние тулзы сравнения и мержинга. Вы выше абсолютно верно написали, что системы контроля версий заточены под текстовые исходники — я просто хотел показать как diff отображается в графическом виде, и что такой код можно мержить. Я так думаю, что в далёком (очень далёком) будущем ситуация изменится и графические функциональные средства разработки постепенно вытеснят классические текстовые, но это произойдет реально нескоро.
          • –1
            с компилятором, написанным на основе LLVM
            См. mono. В наличии LLVM-бакэнд rjljutythfwbb и возможность жить без JIT.
            • –1
              Смотрел. Года два я очень пристально на него смотрел, так как C# (но без обвязки Microsoft) — мой любимый язык. Но mono — очень тяжел, к тому же имеет такую лицензию, что встраивать его в свои приложения можно только за деньги.
              • –1
                Эм? Встраивать только за деньги? Весь код реализации фреймворка под лицензией MIT, libmono под LGPL, линкуйтесь динамически и всё будет лицензионно чисто и бесплатно. С тяжеловесностью можно поспорить: если тащить за собой только нужное, то вполне можно уложиться в 5-10 мегабайт в запакованном виде, память же в рантайме оно кушает довольно аккуратно.
  • +6
    malloc принимает количество байт и возвращает указатель на void, который вам надо кастить во что-то более удобное — придумать худшее API для управления памяти тяжело

    Кажется, автору не стоит позориться незнанием C. В чистом C любой указатель кастится к void*, и void* неявно кастится к любому указателю:
    char *string = malloc(len); /* no errors and no warnings in C */ void *ptr = string; /* no errors, no warnings in both C and C++ */

    Зачем использовать malloc/free, когда файл исходника имеет расширение cpp для меня большая загадка, разве что кроме случая, когда пишется плюсовый wrapper для сишной библиотеки.

    указатели — это зло.

    И тут я понял, что весь пост — это такая шутка юмора, расслабился и пошел по своим делам.
    • +2
      Бьерн Страустроуп подчеркивает, насколько важна обратная совместимость для С++.

      Умный мужик между прочим. Кому нужен SuperDuperLanguage, для которого нет библиотек (бинарная совместимость с C, в т. ч. в виде костыля extern «C») и ежегодно выходят все новые и новые версии, которые каждый раз на 20% круче и на 80% несовместимы, вынуждая вас либо переписывать код, который работает, либо сидеть на старой версии языка (превед, python 3!)
  • 0
    Вот моя история:
    эволюция с использования стандартных библиотек типа core data в сторону примитивов NSArray, NSObject основанных на С у меня совпала с эволюцией apple в сторону C++. Почему так — 85% падений в С++ коде аппла.
    Сборка boost под iOS в 2013 году напомнила сборку java applet в году эдак 96м (кто помнит тот в курсе, не вместятся маты в сообщение)
    Видимо С++ дает возможность программисту в его части проекта наделать херни и при этом дает повод его не найти и поругать систему.
    Вообще — давайте себе признаемся в том что врядли легко принять — большая часть языков на рынке создано не для того чтобы был happy coding а для того чтобы была работа для всех, а не только для людей которые ПОНИМАЮТ ЧТО ОНИ ДЕЛАЮТ И КАК ОНО РАБОТАЕТ.
  • +1
    Нынче модный тренд — ругать С++… Но идеалов нет, и вполне может быть, что некоторые восхваляемые на данный момент языки скоро так же будут поругиваться. Не стоит смотреть однобоко и давать 1001 подтверждение того, что С++ уже так безнадежен.
    • +2
      OCaml лучше С++ со всех сторон.
      • +2
        Я думаю, к этому разговору можно будет вернуться лет через двадцать.
    • 0
      что некоторые восхваляемые на данный момент языки скоро так же будут поругиваться.

      Есть ли языки, которые не ругают с момента выхода их в свет? :)
      • +4
        Как-то в одной конторе был очередной обеденный треп с поругиванием очередного продукта. И было замечание одного коллеги, что есть ПО, которое ругают, а есть, которое не используют.
        • +2
          Зачастую люди даже не пробовали использовать, а уже ругают :)
        • 0
          There are only two kinds of languages: the ones people complain about and the ones nobody uses.
          Bjarne Stroustrup
  • +11
    — Маамаааа! Этот язык программирования предоставляет мне выбор! Слишком много выбора! Мне страшно, мама! Можно я попишу на Бейсике? (с) :-)
  • +1
    Хотел было откомментить, но пока я лично не увижу написанный на глубокоуважаемом автором Haskell'е проект серьезнее «лабы» (не требую операционную систему или игру, согласен на что-либо уровня firefox / utorent / netbeans либо nginx / redis / mc ) даже в спор вступать не вижу смысла. Лисп тоже отец всех языков, ну и.
    • 0
      P.S: Xmonad не предлагать, это несерьёзно
      • 0
        Автор — Бартош Милевски. Я не знаю, что именно он написал на Haskell, можно посмотреть тут: bartoszmilewski.com/category/haskell/
    • 0
      Видел, как некоторые пользовались en.wikipedia.org/wiki/Darcs
  • –4
    Мне не понятно, как автор с таким невежеством умудрился попасть в лучшие посты.
  • –5
    Про управление памятью на примере структуры вообще смешно. Автор про классы слышал?
    • +6
      Статья — перевод, автор — Бартош Милевски. Я думаю, что он наверняка слышал про классы:)
  • –4
    Таким образом, на замену malloc пришел оператор new, который тоже сломан: он возвращает опасный указатель, а указатели — это зло.

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

    Если руки растут из места где спина теряет свое гордое название то никакой язык программирование не поможет.
    Мое имхо — С++ еще переживет всех предсказателей смерти С++

    ЗЫ статья нубская. Очередная страшилка про злые и опасные указатели которые едят маленьких детей.
    да и я поставил минус.
    • +3
      зачем минусовать переводчика, если не нравится автор? Такие как вы в свое вермя убивали гонцов с плохими новостями.
      • –5
        зачем минусовать переводчика, если не нравится автор? Такие как вы в свое вермя убивали гонцов с плохими новостями.

        зачем переводить неадекватное говно? Более того есть устойчивое ощущение что автор несколько далек от темы которую взялся переводить.
        • +5
          ваше несогласие с автором не делает его статью «неадекватным говном».
          • –1
            Хорошо.
            По другому поясню свою мотивировку: Я не считаю адекватным ни статью ни перевод статьи, где идет речь о том что электрические розетки опасны и может ё*нуть током. Что 127 воль ё*бнет чуть менее чем 220 но все равно мало не покажется. Что лучший выход это 12V но там нужны толстые провода под ток 100+А. А еще лучше замуровать розетку совсем.

            Спасибо кэп. 100 из 100 в курсе что может ё*бнуть током и что надо быть поаккуратнее с электричеством.
            И что же автор нового нам хотел сказать????
            • 0
              по-моему, пользуясь вашей аналогией, в статье идет разговор о том, что попыткта сделать универсальную розетку заканчивается постоянными ударами тока, и что как бы пора уже перейти на новый стандарт розеток и прекратить идти на поводу у людей со старым напряжением, но никто этого делать не хочет и все продолжают терпеть удары током.
              • –1
                по-моему, пользуясь вашей аналогией, в статье идет разговор о том, что попыткта сделать универсальную розетку

                Ну не знаю где вы про универсальную розетку увидели аллегорию. Я увидел тупое предостережение: Товарищ, не влезай! Ё*нет током.

                но никто этого делать не хочет и все продолжают терпеть удары током.

                — Техника безопасности? Нет не слышали.

                ЗЫ лично меня током не бьет ни в жизни, ни в С++ в аллегорическом плане
  • +1
    Кидайтесь в меня камнями, но я вот чего не понимаю:
    каждый раз когда я раздумываю или гуглю на тему «а почему нет компилятора питона в машинный код», поднимаются тонны контраргументов типа «сложные типы данных», «хитрые особенности языка».

    Но вот вопрос: а в современном C++ этих особенностей меньше, что-ли? Все эти smart pointers, темплейты, головоломные оптимизации, итд итп?
    • +1
      Это две совсем разные вещи. В python «сложные типы данных» и «хитрые особенности языка» относятся к сложности их реализации в компилируемом языке, а в C++, к сожалению, к использованию, а реализация у них несколько упрощена, как раз ценой усложнения использования. Один плюс — они работают и компилируются в native code.
    • 0
      Для статической компиляции в машинный код необходимо провести статический анализ программы.
      Для динамических языков, вроде питона, это в общем случае проделать невозможно — грубо говоря, невозможно заранее определить, что должен делать код, не выполнив его.
      За примерами далеко ходить не надо: eval() в одиночку сводит любую возможность компиляции в машинный код на нет.
      • 0
        Ок, убрали динамическую компиляцию из питона, получили транслирующийся в C/C++ шустрый Cython. Но, насколько я понимаю, он всё равно медленнее чистого C++. Почему?
        • +1
          Потому что компилятором си дольше и серьёзнее занимаются.
  • –1
    Люди, которые кричат о «кривости» С/С++ и отправляют его на пенсию, наверно, забывают, что ВСЕ! современные распространенные (не берем во внимание какие-то специфические) операционные системы написаны не на Haskel, не на Java, не на Python или Ruby. Что почти ВСЕ компиляторы/интерпретаторы/трансляторы/виртуальные машины для других языков написаны тоже на С/С++!.. А не чем написаны большинство СУБД? А не чем написаны сервисы/серверы для тех операционных систем, которые написаны на С++?
    • +3
      Просто очень мало нормальных языков для системного программирования существует, вот и пользуются все попсовым С++.
      Тем не менее, даже для системного программирования С++ далеко не идеален из-за своего сишного наследия.
      • 0
        вот и пользуются все попсовым С++.
        Тем не менее, даже для системного программирования С++ далеко не идеален из-за своего сишного наследия.


        а какие альтернативы?
        • +1
          D. Теоретически язык отличный, индустрии всего-то осталось взять, навалиться скопом и дописать уже нормальный компилятор и библиотеки. Поработать плотно лишний месяц или год, зато потом наслаждаться десятилетиями.

          Но нет, всем влом, «моя хата с краю», лучше ещё раз помучаюсь с C++.
          • 0
            Си может работать на голом железе и сам реализовать все библиотечные функции. А другим языкам нужен runtime, который должен быть над программой. Поэтому оси и драйвера сложнее писать. Нужно минимальное ядро на том же си.
            • +1
              Почти все языки того поколения обходились без Runtime. Паскаль, например. Однако остальные сошли с дистанции. «Голый» Си удобен прежде всего тем, что он — «кроссплатформенный ассемблер». То есть язык настолько туп и близок к железу, насколько это возможно при наличии строгой типизации, циклов, функций и прочих высокоуровневых абстракций.

              Си шикарно сочетает в себе самостоятельность, о которой вы написали, легкую читабельность, сравнимую с высокоуровневыми языками, кроссплатформенность и почти ассемблерную мощь.
          • +1
            Нам бы в новом проекте сейчас идеально подошел D. Но отсутствие _нормальной_ нативной библиотеки линейной алгебры заставило рассматривать другие варианты. Выбрали Julia, вроде бы, почти идеально, но уж больно она пока сырая.

            Это я к чему, если есть желание, то напишите хорошую библиотеку ЛА для D. Сделаете очень хорошее дело. Если начнете — обещаю подключусь.
            • +1
              А что именно вам нужно от библиотеки ЛА? От предметной области сильно зависит скоуп такой библиотеки. В геймдеве, например, не нужны обобщения векторных произведений, а в деформативном моделировании — суперскалярные операции.

              Вообще, я давно хотел попробовать D, ну и с линейной алгеброй немного знаком. Если это кому-то надо, могу попробовать заняться.
              • 0
                На самом деле не так много: матрично-векторная арифметика, определитель, норма фробениуса и евклидова, обратная и псевдообратная матрицы, сингулярное разложение. Пока, кажется, только это используем. Может быть, что-то забыл или в будущем что-то еще понадобится.
                • +1
                  В Джулии просто целый зоопарк разложений, там писать и писать :-)

                  Ок, почитаю-поиграюсь с языком, в понедельник определюсь окончательно. Кое-что я уже переписывал на плюсах, питоне и шарпе, — в принципе видение задачи есть. Меня, конечно, смущает, что про D я пока только введение Александреску читал, но с другой стороны не боги горшки обжигают: будет востребовано — будет комьюнити, будет комьюнити — научат как надо.
                  • +1
                    Да, Julia очень хорошая задумка. Только сейчас там баг на баге всплывает. Наверное, и от нее откажемся.

                    А про D, я так же только эту книгу прочитал, ничего существенного на нем не писал. Но книга и язык впечатлили.
                    • +1
                      Ну, как-то начал: github.com/akalenuk/la
                      • +1
                        Я не знаю D, но неужели там нет типа, аналогичного site_t в c++ stdlib?
                        Режет глаз повсеместное использование ulong для индексов. Для x86, длинные индексы это оверкилл, но должно легко меняться при переходе на x64.
                        • 0
                          Есть, и вообще его там и надо :-)
                        • 0
                          Спасибо, исправил.
            • +1
              Julia, на мой взгляд (игрался где-то пол года назад), совсем сырой язык и пока не подходит для реальных проектов. Не страшно его использовать? А вообще задумка у них очень хорошая — простота языка, сравнимая с Matlab/Python, направленность на математические пакеты/векторизацию/параллелизм и скорость, сравнимая с C/C++.
    • НЛО прилетело и опубликовало эту надпись здесь
      • НЛО прилетело и опубликовало эту надпись здесь
    • +4
      Не смешивайте Си и Си плюс плюс. О Си речи в статье не шло. Си — язык системного программирования, от него никто не ждёт простоты использования или высокой скорости разработки. А вот для разработки ПО для конечного пользователя и удобство, и скорость важны.
  • 0
    Haskell, конечно, хорош, но там много собственных проблем. Space leaks, оптимизация, извечная борьба с ленивостью, сложные для восприятия абстракции. К слову, упомянутая книжка Саймона Марлоу действительно великолепна.

    Приходится мириться с тем, что есть ряд задач, в которых требуется максимизация отношения полезные инструкции/киловатт. В мобильных устройствах, к примеру. На том же Going Native 2013 Александреску объяснял, что для фейсбука (где он сейчас работает) повышение производительности даже на несколько процентов — хорошая оптимизация и неплохая экономия. Ради этого они делают страшные и некрасивые вещи вроде собственных таблиц виртуальных функций. Язык, конечно, сложный, но что делать, наследие. Я пришёл к нему после 4 лет промышленной Java, и, если честно, не особо горю желанием возвращаться. Хотя многих вещей не хватает. D&E Страуструпа поясняет, почему всё именно так, как оно есть…

    В комментариях видел отсылки к Golang — это действительно отличный и стабильный язык, глоток свежего воздуха в совтверном мире, поросшем слоями абстракций. Многие вещи там сделаны очень правильно, программировать на нём довольно приятно (порой почти также приятно, как на Haskell). Огорчает в основном отсутствие аналога шаблонов, что порой вынуждает писать однообразный код. Причём неизвестно, когда это исправят, и исправят ли вообще.

    Недавно узнал про язык Clay, думаю посмотреть на него поближе на досуге. Выглядит многообещающе.
  • +2
    По-моему, Макконнелл в своей книге «Совершенный код» очень мудро посоветовал разрабатывать не на языке, а с использованием языка… и объяснил, что это означает. Очень применимо к данной статье.
  • 0
    Именно поэтому я давно и прочно предпочитаю использовать С вместо С++.

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