Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
С++.docx
Скачиваний:
3
Добавлен:
01.05.2025
Размер:
201.45 Кб
Скачать

Влияние и альтернативы

Ввиду изобилия критики в адрес С++, неоднократно предпринимались попытки предложить альтернативы C++, как для прикладного, так и для низкоуровневого программирования (не заявляемые как «универсально применимые» языки).

Одной из первых альтернатив в прикладном программировании стал язык Java, разработанный Sun, который часто ошибочно считают прямым потомком C++. На деле в Java от С++ нет ничего, кроме синтаксиса — семантика Java унаследована от языка Модула-2, и основы семантики C++ (такие как система типов, основанная на адресной арифметике, ручное управление памятью, умышленный отказ от фундаментального принципа ООП «всё — объект», и др.) в Java не прослеживаются. Семантика отдельных операторов также отличается: например, безусловный переход в Java отсутствует, а ключевое слово goto использовано для финализации (разновидности условного перехода). Кроме того, элементы семантики Си, унаследованные из Lisp (такие как функции высших порядков, функции с неограниченным числом аргументов и тернарная условная операция), в Java отсутствуют. Нет в Java и макроопределений времени компиляции. Всё это заметно меняет идеологию программирования на языке (хотя и сохраняет её в рамках общей идеологии потомков Алгола). Для улучшения коньюнктуры создатели Java выбрали синтаксис C++ и поощрили их сравнение в печати. Учитывая всё это, а также генеалогию языков (Modula-2 является потомком Симулы, как и С++, но им не является Си), Java правильнее называть «троюродным племянником» С++, нежели «наследником». По тому же пути пошла компания Microsoft, предложив язык C#.

После того, как было получено общественное признание Java и C#, были произведены попытки совмещения безопасности и скорости разработки, характерных для Java и C#, с эффективностью C++ — так появился язык D и диалект Managed C++, не получившие широкого признания. Одновременно с развитием Алголовского направления, сторонники функционального программирования и рефлексивного метапрограммирования предприняли попытку совместить модель типизации Хиндли-Милнера и макро-подмножество Common Lisp с языком C#, создав язык Nemerle. Его также зачастую стали рассматривать как «конкурент C++», что способствовало росту популярности функционального программирования и рефлексивного метапрограммирования[33] и побудило Microsoft дополнить базовый комплект своей среды разботки для C++ и C# (Visual Studio) компилятором языка F# — диалекта ML, адаптированного для совместимости с C#. Резонно полагать, что те же цели преследовали разработчики языков Scala и JavaScript — гибридных функционально-объектно-ориентированных языков, также унаследовавших синтаксис С++, но ориентированных на совместимость с Java.

Старейшим конкурентом С++ в задачах низкого уровня является Objective-C, совмещающий Си с объектной моделью Smalltalk. Из-за их соперничества долгое время полагалось, что эффективность и низкоуровневые возможности Си могут использоваться в сложно структурированных высокоуровневых задачах только посредством облачения их в ту или иную объектную модель. Однако, накопленные за многие годы достижения в сфере ФП позволили предложить альтернативный путь развития языка Си — совмещение его не с объектно-ориентированным, а с аппликативным программированием, то есть улучшение абстракции, строгости и модульности низкоуровневых программ посредством обеспечения не инкапсуляции изменяемого состояния, а наоборот, предсказуемости поведения и ссылочной прозрачности. Примерами работ в этом русле служат языки BitC, Cyclone и Limbo. Хотя есть и успешные попытки применения ФП в задачах реального времени без интеграции со средствами Си[34][35], всё же на данный момент (2013 г.) в низкоуровневой разработке применение в той или иной мере средств Си имеет лучшее соотношение трудоёмкости с результативностью. Много усилий было приложено разработчиками Python и Lua для обеспечения использования этих языков программистами на С++, так что из всех языков, достаточно тесно связанных с ФП, именно они чаще всего отмечаются в совместном использовании с С++ в одном проекте. Наиболее значимыми точками соприкосновения С++ с ФП можно считать привязки разработанных на С++ библиотек wxWidgets и Qt с характерной для С++ идеологией к языкам Lisp, Haskell и Python (в большинстве случаев привязки к функциональным языкам делают для библиотек, написанных на Си или на других функциональных языках).

Прямой потомок С++ на данный момент лишь один — язык D.

Сравнение Java и С++

См. также: en:Comparison of Java and C++

Java и C++ часто сравниваются как языки, унаследовавшие синтаксис Си, несмотря на огромные различия на всех уровнях, от семантики до сферы применимости. Можно сказать, сравнение С++ с Java идёт вторым по частоте после сравнения С++ с Си.

Целевая ниша 

Java позиционируется для весьма конкретного сектора промышленности: безопасный язык с низким порогом вхождения для разработки прикладных пользовательских приложений широкого рынка с высокими показателями портируемости[36] — и с этой задачей справляется. С++ претендует на «универсальную применимость» во всех задачах для всех категорий программистов, но не удовлетворяет в полной мере требованиям ни одной из заявленных сфер применимости (см. раздел Критика).

Исполнение программы 

Java имеет формальную семантику, ориентированную на интерпретацию, но код Java компилируется в промежуточный код, который непосредственно перед запуском программы компилируется в машинный (иногда говорят об интерпретации байт-кода, но в данном случае это неверно — у современных наиболее распространённых сред исполнения Java оба этапа трансляции являются полностадийными, не ограничиваясь работой в рамках AST, с соответствующим сужением возможностей). C++ имеет естественную семантику, ориентированную на компиляцию, так что уже на аппаратной Java-машине был бы крайне неэффективен и ограничен по возможностям. Одно это определяет разницу в сферах применения языков: Java нецелесообразно использовать в низкоуровневом программировании; С++ — в разработке интернет-приложений. Механизм исполнения Java делает программы полностью портируемыми, по принципу «написано один раз — запускается везде (write once — run everywhere)», хотя это не было первостепенной целью разработчиков. Стандартное окружение и среда исполнения позволяют выполнять программы на Java на любой аппаратной платформе и в любой ОС без каких-либо изменений, при условии существования на данной ОС и платформе среды исполнения. Усилия по портированию программ минимальны, и могут быть сведены к нулю соблюдением определённых рекомендаций при разработке. Ценой портируемости в данном случае становятся определённые накладные расходы (например, размер среды исполнения Java превышает даже их размеры у всех функциональных языков).

Парадигма программирования 

Java в значительно более высокой степени, чем С++, отвечает фундаментальному принципу ООП «всё — объект» (но не в абсолютной — методы классов самостоятельными объектами не являются, в отличие от CLOS или Python). Для объявления глобальных функций или переменных в Java их необходимо оборачивать в фиктивные классы и назначать свойство статичности[37]. Для задания главной функции даже самой простой программы на Java необходимо поместить её в класс[38]. Программировать на Java в функциональном стиле затруднено[источник?], поскольку на уровне синтаксиса языка нет поддержки основных элементов ФП (таких как функций высшего порядка) и нет средств макрорасширения языка.

Объектная модель 

Как и в С++, объектная модель Java наследуется из Симулы (в Java — через промежуточную ступень — язык Modula-2), то есть фундаментально отличается от оной в потомках языка Smalltalk (Objective-C, Python, Ruby). Но есть серьёзные отличия и от С++. В Java все методы являются виртуальными. Есть синтаксический сахар для определения абстрактных классов: использование ключевого слова interface делает все методы класса чистыми виртуальными — такие классы называются в Java «интерфейсами». Множественное наследование допустимо только для них, но не для обычных классов, что улучшает дисциплину программирования — на этапе реализации нет возможности нарушить структуру проекта, построенную на этапе архитектурного проектирования (в С++ это делается легко).

Операторы 

Безусловный переход в Java отсутствует. Тернарная условная операция в Java также отсутствует. Однако, большинство конструкций являются типичными для всех потомков Алгола: императивный порядок вычислений, присваивания, ветвления, циклы, инфиксные арифметические операции, аргументы в объявлениях и вызовах функций, и пр. В целом спецификация Java отвечает принципу наименьшего удивления и позволяет быстрый переход на Java с любого языка семейства Алгола. Однако, есть и исключения — например, Java, как и C++, позволяет пропускать break в ветви оператора switch[39].

Синтаксис 

Основные конструкции Java и характерное оформление блоков кода наследованы из Си; большинство синтаксических отличий обусловлены разницей в семантике. Спецификаторы видимости компонентов класса в Java указываются на каждый компонент, а не группами, как в С++. В Java нет механизма ввода синтаксического сахара в программу — перегрузки операторов.

Адресная арифметика 

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

Кодогенерация 

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

Интроспекция 

В C++ RTTI ограничена возможностью сравнивать типы объектов между собой и с буквальными значениями типов. В системе Java доступна более подробная информация о типах.

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

C++ позволяет использовать принцип «захват ресурсов путём инициализации» (RAII), при котором ресурсы ассоциированы с объектом и автоматически освобождаются при разрушении объекта (например, std::vector и std::ifstream). Также возможен подход, когда программист, выделяя ресурсы (память под объекты, открытые файлы и т. п.), обязан явно позаботиться о своевременном их освобождении. Java работает в среде со сборкой мусора, которая автоматически отслеживает прекращение использования объектов и освобождает занимаемую ими память, если в этом есть необходимость, в некоторый неопределённый момент времени. Ручное управление предпочтительнее в системном программировании, где требуется полный контроль над ресурсами, RAII и сборка мусора удобнее в прикладном программировании, поскольку в значительной степени освобождают программиста от необходимости отслеживать момент прекращения использования ресурсов. Сборщик мусора Java требует системных ресурсов, что снижает эффективность выполнения программ, лишает программы на Java детерминированности выполнения и способен следить только за памятью. Файлы, каналы, сокеты, объекты графического интерфейса программист на Java всегда освобождает явно.

Окружение 

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

См. также

  • wxWidgets

  • Qt

  • Тернарная условная операция в С++

  • Стандартная библиотека языка Си

  • Стандартная библиотека языка C++

Примечания

↑ Показывать компактно

  1. Шилдт, 1998, с. 57

  2. Страуструп, 1999, 2.1. Что такое C++?, с. 57

  3. Стэнли Липпман, Pure C++: Hello, C++/CLI  (англ.)

  4. Jump up to: 1 2 Страуструп, 1999, 1.4. Исторические замечания, с. 46

  5. C++ — Standards

  6. Bjarne Stroustrup. C++ Glossary. Проверено 8 июня 2007. Архивировано из первоисточника 27 мая 2012.

  7. Jump up to: 1 2 Страуструп, Дизайн и эволюция C++, 2007

  8. Страуструп, 1999, 1.6

  9. ISO/IEC 14882:1998, раздел 6.4, пункт 4: «The value of a condition that is an initialized declaration in a statement other than a switch statement is the value of the declared variable implicitly converted to bool … The value of a condition that is an expression is the value of the expression, implicitly converted to bool for statements other than switch; if that conversion is ill-formed, the program is ill-formed».

  10. STLport: Welcome!

  11. Интервью Б. Страуструпа LinuxWorld.com

  12. Интервью Б. Страуструпа журналу «Системный администратор»

  13. CNews: Эксклюзивное интервью с создателем языка программирования C++

  14. Jump up to: 1 2 Alan Kay's Definition Of Object Oriented Programming. Архивировано из первоисточника 13 августа 2013.

  15. Jump up to: 1 2 3 Mаrtin Ward Language Oriented Programming. — Computer Science Department, Science Labs, 1994.

  16. Paul Hudak Modular Domain Specic Languages and Tools. — Department of Computer Science, Yale University.

  17. Андрей Карпов 20 ловушек переноса Си++ - кода на 64-битную платформу. — RSDN Magazine #1-2007, 25.04.2007.

  18. Ian Joyner A Critique of C++ and Programming and Language Trends of the 1990s - 3rd Edition. — копирайт и список изданий.

  19. В качестве контр-примеров можно рассмотреть синтаксис нескольких языков, семантически намного более мощных, чем С++:

      • определение минимального ядра языка Lisp (относимого к метаязыкам) представляет собой всего 7 конструкций, его реализация на самом Лиспе занимает всего 15 строк кода (хотя в таком варианте Лисп мало применим в промышленности); стандарт R6RS диалекта Scheme содержит 23 строки РБНФ (из которых 11 являются лишь «синтаксическим сахаром»); при этом «код» и «данные» в Лиспе определяются и используются единообразно — за счёт этого рефлексивное метапрограммирование оказывается рутинным делом.

      • ядро Форта (также относимого к метаязыкам) реализуется за день на Ассемблере; простейший интерпретатор Тьюринг-полного языка — семантического аналога Форта (не эффективного и не предназначенного для реального использования во встраиваемых системах — см. игрушечный язык программирования), реализуется за считанные минуты на многих ЯВУ.

      • компилятор минимального подмножества языка OCaml на нём самом занимает всего порядка пятисот строк кода.

  20. Walid Taha Domain-Specic Languages. — Department of Computer Science, Rice University.

  21. Lugovsky V.S. Using a hierarchy of Domain Specic Languages in complex software systems design. — 2008.

  22. Страуструп, Программирование: принципы и практика использования C++, 2001

  23. Dave Gottner. Templates Without Code Bloat. — Dr. Dobb's Journal, январь 1995.

  24. Adrian Stone. Minimizing Code Bloat: Redundant Template Instantiation. Game Angst (22 сентября 2009). Проверено 19 января 2010. Архивировано из первоисточника 27 мая 2012.

  25. Herb Sutter. C++ Conformance Roundup. — Dr. Dobb's Journal, январь 2001.

  26. Are there any compilers that implement all of this?. comp.std.c++ frequently asked questions / The C++ language. Comeau Computing (англ.) (10 декабря 2008). Проверено 19 января 2010. Архивировано из первоисточника 27 мая 2012.

  27. Scott Meyers. Code Bloat due to Templates. comp.lang.c++.moderated. Usenet (16 мая 2002). Проверено 19 января 2010.

  28. Jump up to: 1 2 3 Ray Tracer Language Comparison (бенчмарк языков программирования — ffconsultancy.com/languages/ray_tracer/)

  29. Boehm H. Advantages and Disadvantages of Conservative Garbage Collection. (ссылка изРеймонд, Эрик. Искусство программирования для Unix.. — 2005. — С. 357. — 544 с. — ISBN 5-8459-0791-8)

  30. Don Clugston, CSG Solar Pty Ltd (Перевод: Денис Буличенко) Указатели на функции-члены и реализация самых быстрых делегатов на С++. — RSDN Magazine #6-2004.

  31. Шилдт, Теория и практика С++, 1996, с. 64-67

  32. Эрик Реймонд Искусство программирования для Unix = en:The Art of Unix. — Издательский дом "Вильямс", 2005. — ISBN 5-8459-0791-8

  33. Чистяков Влад aka VladD2 Синтаксический сахар или C++ vs. Nemerle :) // RSDN Magazine #1-2006. — 24.05.2006.

  34. Zhanyong Wan, Walid Taha. Архивировано из первоисточника 13 августа 2013., and Paul Hudak Event-Driven FRP // Department of Computer Science, Yale University.

  35. MLKit. Архивировано из первоисточника 1 августа 2013.

  36. 1.2 Design Goals of the Java™ Programming Language. Oracle (1 января 1999). Проверено 14 января 2013.

  37. Class Arrays, JavaTM 2 Platform Std. Ed. v1.4.2

  38. The Java Tutorials. A Closer Look at the «Hello World!» Application

  39. The Java Tutorials: The switch Statement

Мнения

  1. Programming Language Popularity (2009). Проверено 16 января 2009. Архивировано из первоисточника 27 мая 2012.

  2. TIOBE Programming Community Index (2009). Проверено 6 мая 2009. Архивировано из первоисточника 27 мая 2012.

  3. Jump up to: 1 2 3 Открытая переписка gmane.comp.version-control.git от 06.09.2007. Архивировано из первоисточника 13 августа 2013.

  4. vanDooren. C++ keyword of the day: export. Blogs@MSMVPs (24 сентября 2008). — «The export keyword is a bit like the Higgs boson of C++. Theoretically it exists, it is described by the standard, and noone has seen it in the wild. … There is 1 C++ compiler front-end in the world which actually supports it»  Проверено 19 января 2010. Архивировано из первоисточника 27 мая 2012.

  5. Наглядной демонстрацией служат многочисленные споры между программистами разного уровня квалификации, которые можно слышать повсеместно, например: * Форум программистов «Linux.ORG», тема «Чем так плох С++?» (msgid=1989166) * Форум программистов «Просто Трёп», тема «С++?» (bid=16&tid=466654) * Форум программистов «HardForum» (ранее «ProgZ.Ru»), тема № 45505 «Самый крутой язык программирования» * Форум программистов «dxdy», тема «Язык программирования для математика» (topic33965) * Форум программистов «RSDN», тема «Так в чем же принципиальные отличия ФП от ИП?» (decl/2473899)

Пояснения

↑ Показывать компактно

  1. Описание в обычном синтаксисе, такое как «decltype(x+y) f(T x, T y)» недопустимо, так как оно нарушало бы общее правило, согласно которому все используемые в программе объекты должны быть объявлены до своего первого использования.

  2. Многие задачи предъявляют к языку особые требования — например, когнитивное моделирование требует единообразного представления кода и данных и наличие рефлексивности непосредственно как части системы типов — хотя языки, отвечающие этим требованиям, в свою очередь, накладывают определённые требования на вычислительные ресурсы, и оказываются неприменимы в ряде архитектур. Существуют и архитектуры, для которых неприменимы языки Си и С++ (например, AVR 1200). В подобных ситуациях единственная возможность «использовать» некий «универсальный» язык (такой как С++) состоит в написании интерпретатора языка, отвечающего требованиям задачи, решении на нём собственно задачи, и преподнесении всего кода как «решения на этом универсальном языке». Однако, подобная структура сама по себе отвергает тезис об «универсальной применимости» рассматриваемого языка, так как де-факто задача была решена на другом языке

  3. Например, Boost.Lambda позиционируется как лямбда-функция, однако С++ не воплощает лямбда-исчисление Чёрча целиком; имитация комбинаторов посредством языка шаблонов слишком затруднено, чтобы ожидать их использование на практике; продолжения, унаследованные от Си, считаются неидеоматичными и опасными, а их реализация посредством языка шаблонов невозможна; кроме того, применение лямбда-лифтинга для оптимизации С++ невозможно,— так что фактчески Boost.Lambda — это просто анонимная функция, а не объект лямбда-исчисления.

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

  5. Очевидно, что если сложность системы или элемента системы превышает порог возможностей человека по осознанию, то система или элемент системы не будут до конца осознаны. При этом трансляция высокоуровневых конструкций (даже всего лишь арифметических выражений) сама по себе является очень сложной задачей: она требует применения динамического программирования и/или большого числа эвристик; даже для эффективного выделения регистров под временные переменные в данном контексте требуется решить задачу раскраски ненаправленного ациклического графа в минимальное число цветов. Таким образом, необходимость решать задачу эффективной трансляции одновременно с полноценной и адекватной реализацией требуемого функционала повышает общую сложность разработки, по меньшей мере, по экспоненциальному закону относительно сложности реализации того же функционала на предметно-ориентированном ЯСВУ, и делает само программирование NP-полным. Учитывая ограниченность способностей человека по восприятию и переработке информации — фактически невозможным, начиная с некоторого (вполне обозримого) порога сложности. Однако, методы трансляции хорошо формализуемы и могут быть воплощены в виде компилятора языка достаточно высокого уровня, обеспечивающего максимальную понимаемость кода, а использование такого языка человеком решает проблему сложности. Таким образом, для любого достаточно сложного алгоритма достаточно развитый компилятор произведёт заведомо более эффективный код, чем человек на языке низкого уровня; и для любых достаточно сложных условий всегда разумнее потратить часть средств на разработку компилятора высокоуровневого предметно-ориентированного языка, чем писать на низкоуровневом языке общего назначения. Всё это хорошо известно в информатике (и именно этим обусловлено появление Фортана, а следом и языков более высокого уровня), но подвергается сомнению сторонниками императивной парадигмы программирования из-за чрезвычайно высокой сложности реализации оптимизирующих трансляторов императивными средствами и заведомой ограниченности возможностей оптимизации императивных языков. В функциональном программировании парсеры реализуются тривиально, а возможностей оптимизации существенно больше, поэтому языково-ориентированное проектирование сложных систем весьма распространено, и вынесение функциональности в код на Си для явного контроля за эффективностью осуществляется лишь при крайней необходимости.

  6. Сборщик мусора удаляет множество объектов за проход, что снимает необходимость как пошагового декремента счётчика, так и многократной передачи управления от кода подсистеме управления памятью и обратно (утверждение верно только для многопоточных умных указателей, также не учитывается время поиска собрщиком мусора кандидатов на удаление).

  7. Как выразился Ж. Ж. Руссо, « Тысячи путей ведут к заблуждению; к истине — только один» — то есть вероятность совершения человеком неправильного выбора оказывается на порядки выше, чем правильного, если де-факто такая возможность ему предоставлена.

Литература

  • Бьёрн Страуструп. Язык программирования C++ = The C++ Programming Language / Пер. с англ. — 3-е изд. — СПб.; М.: Невский диалектБином, 1999. — 991 с. — 3000 экз. — ISBN 5-7940-0031-7 (Невский диалект), ISBN 5-7989-0127-0 (Бином), ISBN 0-201-88954-4 (англ.)

  • Бьёрн Страуструп Язык программирования C++. Специальное издание = The C++ programming language. Special edition. — М.: Бином-Пресс, 2007. — 1104 с. — ISBN 5-7989-0223-4

  • Бьёрн Страуструп Программирование: принципы и практика использования C++, исправленное издание = Programming: Principles and Practice Using C++. — М.: Вильямс, 2011. — С. 1248. — ISBN 978-5-8459-1705-8

  • Бьёрн Страуструп Дизайн и эволюция C++ = The Design and Evolution of C++. — СПб.: Питер, 2007. — 445 с. — ISBN 5-469-01217-4

  • Сиддхартха Рао Освой самостоятельно C++ за 21 день, 7-е издание (C++11) = Sams Teach Yourself C++ in One Hour a Day, 7th Edition. — М.: «Вильямс», 2013. — 688 с. — ISBN 978-5-8459-1825-3

  • Стефенс Д. Р. C++. Сборник рецептов. — КУДИЦ-ПРЕСС, 2007. — 624 с. — ISBN 5-91136-030-6

  • Стивен Прата. Язык программирования C++ (C++11). Лекции и упражнения = C++ Primer Plus, 6th Edition (Developer’s Library). — 6-е изд. — М.: Вильямс, 2012. — 1248 с. — ISBN 978-5-8459-1778-2

  • Айвор Хортон. Visual C++ 2010: полный курс = Ivor Horton’s Beginning Visual C++ 2010. — М.: Диалектика, 2010. — С. 1216. — ISBN 978-5-8459-1698-3

  • Герберт Шилдт. Полный справочник по C++ = C++: The Complete Reference. — 4-е изд. — М.: Вильямс, 2011. — С. 800. — ISBN 978-5-8459-0489-8

  • Герберт Шилдт Теория и практика С++ = Shildt's Expert C++. — СПб.: BHV — Санкт-Петербург, 1996. — ISBN 0-07-882209-2, 5-7791-0029-2

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]