Сравнение Java и C ++ - Comparison of Java and C++

Это сравнение Ява и C ++, два выдающихся объектно-ориентированный языки программирования.

Цели дизайна

Различия между языками программирования C ++ и Java можно проследить до их наследие, поскольку у них разные цели дизайна.

C ++ был разработан для программирования систем и приложений (т.е. инфраструктурное программирование), расширяя процедурное программирование язык C, который был разработан для эффективного выполнения. В C, C ++ добавлена ​​поддержка объектно-ориентированного программирования, Обработка исключений, управление ресурсами на основе времени жизни (RAII ), общее программирование, метапрограммирование шаблона, а Стандартная библиотека C ++ который включает общие контейнеры и алгоритмы ( Стандартная библиотека шаблонов или STL) и многие другие средства общего назначения.

Java - это универсальный, параллельный, объектно-ориентированный язык программирования на основе классов, который разработан для минимизации зависимостей реализации. Он опирается на Виртуальная машина Java быть безопасный и очень портативный. Он поставляется в комплекте с обширной библиотекой, предназначенной для обеспечения полной абстракции базовой платформы. Java - это объектно-ориентированный язык со статической типизацией, использующий синтаксис, аналогичный (но несовместимый с) C ++. Он включает систему документации под названием Javadoc.

Различные цели в разработке C ++ и Java привели к разным принципам и компромиссам между языками. Отличия заключаются в следующем:

C ++Ява
Расширяется C с участием объектно-ориентированного программирования и общее программирование. Наиболее правильно можно использовать код C.Сильно подвержен влиянию синтаксиса C ++ / C.
Совместим с C исходный код, за исключением нескольких угловые случаи.Обеспечивает Собственный интерфейс Java и недавно Собственный доступ Java как способ прямого вызова кода C / C ++.
Пишите один раз, компилируйте где угодно (WOCA).Напишите один раз, бегите куда угодно / везде (WORA / WORE).
Позволяет процедурное программирование, функциональное программирование, объектно-ориентированного программирования, общее программирование, и метапрограммирование шаблона. Выступает за сочетание парадигм.Позволяет процедурное программирование, функциональное программирование (начиная с Java 8) и общее программирование (начиная с Java 5), ​​но настоятельно рекомендует объектно-ориентированный парадигма программирования. Включает поддержку для создания языки сценариев.
Выполняется как собственный исполняемый машинный код для цели Набор инструкций (s).Работает на виртуальная машина.
Предоставляет типы объектов и имена типов. Позволяет отражать через информация о типе времени выполнения (RTTI).Является отражающий, позволяя метапрограммировать и генерировать динамический код во время выполнения.
Имеет несколько стандартов двоичной совместимости (обычно Microsoft (для компилятора MSVC) и Itanium / GNU (почти для всех других компиляторов)).Имеет один стандарт двоичной совместимости, кросс-платформенный для ОС и компилятора.
Дополнительный автоматизированный проверка границ (например, в() метод в вектор и строка контейнеры).Все операции должны проходить обязательную проверку всеми совместимыми дистрибутивами Java. HotSpot может убрать проверку границ.
Родной беззнаковая арифметика поддержка.Собственная беззнаковая арифметика не поддерживается. Java 8 кое-что меняет, но аспекты неясны.[1]
Стандартизированные минимальные пределы для всех числовых типов, но фактические размеры определяются реализацией. Стандартизированные типы доступны через стандартную библиотеку <cstdint>.Стандартизированные пределы и размеры всех примитивных типов на всех платформах.
Указатели, ссылки и передача по значению поддерживаются для всех типов (примитивных или определяемых пользователем).Все типы (примитивные типы и ссылочные типы) всегда передаются по значению.[2]
Управление памятью осуществимо вручную через новый / удалить, автоматически по области действия или с помощью интеллектуальных указателей. Поддерживает детерминированное разрушение объектов. Вывоз мусора ABI стандартизирован в C ++ 11, хотя компиляторы не обязаны реализовывать сборку мусора.Автоматический вывоз мусора. Поддерживает недетерминированный метод finalize (), использование которого не рекомендуется.[3]
Управление ресурсами может выполняться вручную или с помощью автоматического управления ресурсами на основе времени жизни (RAII ).Управление ресурсами, как правило, должно выполняться вручную или автоматически с помощью финализаторов, хотя обычно это не рекомендуется. Имеет try-with-resources для автоматического управления ресурсами на основе области действия (начиная с версии 7).

Это также можно сделать с помощью внутреннего API sun.misc.Unsafe но такое использование крайне не рекомендуется и будет заменено общедоступным API в следующей версии Java.

Поддерживает классы, структуры (пассивная структура данных (PDS)) и объединений, и может размещать их на куча или стек.Классы распределяются по куча. Java SE 6 оптимизирует с анализ побега разместить некоторые объекты на стек.
Позволяет явно переопределять типы и некоторые неявные сужающие преобразования (для совместимости с C).Жесткий безопасность типа кроме расширяющихся преобразований.
В Стандартная библиотека C ++ был разработан, чтобы иметь ограниченный объем и функции, но включает поддержку языка, диагностику, общие утилиты, строки, языковые стандарты, контейнеры, алгоритмы, итераторы, числовые значения, ввод / вывод, генераторы случайных чисел, синтаксический анализ регулярных выражений, средства многопоточности, характеристики типов (для самоанализа статических типов) и стандартная библиотека C. В Библиотека Boost предлагает больше функций, включая сетевой ввод / вывод.

Существует большое количество сторонних библиотек для графического интерфейса пользователя и других функций, таких как: Адаптивная коммуникационная среда (ACE), Крипто ++, различный XMPP Мгновенное сообщение (IM) библиотеки,[4] OpenLDAP, Qt, gtkmm.

Стандартная библиотека расширялась с каждым выпуском. К версии 1.6 библиотека включала поддержку локалей, журналов, контейнеров и итераторов, алгоритмов, программирования графического интерфейса (но без использования системного графического интерфейса), графики, многопоточности, сети, безопасности платформы, самоанализа, загрузки динамических классов, блокировки и отсутствия -блокировка ввода / вывода. Он предоставил интерфейсы или классы поддержки для XML, XSLT, MIDI, подключение к базе данных, службы имен (например, LDAP ), криптография, службы безопасности (например, Kerberos ), службы печати и веб-службы. SWT предлагал абстракцию для графических интерфейсов, зависящих от платформы, но был заменен JavaFX в последних выпусках; что позволяет ускорять графику и настраивать пользовательский интерфейс на CSS. Хотя он не поддерживает никакой поддержки «родного вида платформы».
Перегрузка оператора для большинства операторов. Настоятельно рекомендуется сохранять значение (семантику).Операторы не могут быть изменены. Язык отменяет + и + = для класса String.
Холостые и множественное наследование классов, включая виртуальное наследование.Поддерживает только одиночное наследование классов.
Шаблоны времени компиляции. Позволяет Тьюринг завершен метапрограммирование.Дженерики используются для достижения базовой параметризации типа, но они не преобразуются из исходного кода в байтовый код из-за использования стирание типа компилятором.
Указатели на функции, объекты функций, лямбды (в C ++ 11 ) и интерфейсы.Ссылки на функции, объекты функций и лямбды были добавлены в Java 8. Классы (и интерфейсы, которые являются классами) могут передаваться как ссылки, а также через SomeClass.class
Нет стандартного встроенного механизма документации. Стороннее программное обеспечение (например, Doxygen ) существуют.Обширный Javadoc стандартная документация по всем системным классам и методам.
const ключевое слово для определения неизменяемых переменных и функций-членов, которые не изменяют объект. Постоянство распространяется как средство обеспечения во время компиляции правильности кода в отношении изменчивости объектов (см. const-правильность ).окончательный предоставляет версию const, что эквивалентно тип * const указатели на объекты и const для примитивных типов. Неизменяемость членов объекта достигается за счет интерфейсов только для чтения и инкапсуляции объектов.
Поддерживает перейти к заявление.Поддерживает метки с циклами и блоками операторов. перейти к зарезервировано, но помечено как «неиспользуемое» в Спецификация Java.
Исходный код можно записать как кросс-платформенный (может быть скомпилирован для Windows, BSD, Linux, macOS, Солярис и т. д., без изменений) и написаны с использованием специфичных для платформы функций. Обычно компилируется в машинный код, его необходимо перекомпилировать для каждой целевой платформы.Скомпилирован в Байт-код Java для JVM. Байт-код зависит от платформы Java, но обычно не зависит от Операционная система специфические особенности.

Особенности языка

Синтаксис

  • Синтаксис Java имеет контекстно-свободная грамматика который может быть проанализирован простым Парсер LALR. Парсинг C ++ сложнее. Например, Фу <1> (3); представляет собой последовательность сравнений, если Foo - это переменная, но создает объект, если Foo - это имя шаблона класса.
  • C ++ допускает константы, переменные и функции на уровне пространства имен. В Java такие сущности должны принадлежать к какому-либо заданному типу и, следовательно, должны быть определены внутри определения типа, либо класса, либо интерфейс.
  • В C ++ объекты являются значениями, а в Java - нет. C ++ использует семантика значений по умолчанию, а Java всегда использует эталонная семантика. Чтобы выбрать семантику ссылок в C ++, можно использовать указатель или ссылку.
C ++Ява
класс Фу {          // Объявляет класс Foo    int Икс = 0;       // Переменная частного члена. Это будет                     // инициализируется 0, если                     // конструктор не установил бы его.                     // (из C ++ 11)    общественный:      Фу() : Икс(0)     // Конструктор для Foo; инициализирует      {}               // x в 0. Если инициализатор был                     // опущено, переменная будет                     // инициализируется значением, которое                     // было дано при объявлении x.      int бар(int я) { // Функция-член bar ()          вернуть 3*я + Икс;      }};
класс Фу {               // Определяет класс Foo    частный int Икс;        // Переменная-член, обычно объявленная                          // как частный для принудительной инкапсуляции                          // инициализируется 0 по умолчанию    общественный Фу() {        // Конструктор для Foo    }                     // конструктор без аргументов, предоставленный по умолчанию    общественный int бар(int я) {        // Элемент метода bar ()        вернуть 3*я + Икс;    }}
Фу а;// объявляет, что a является значением объекта Foo,// инициализируется конструктором по умолчанию.// Другой конструктор можно использовать какФу а(аргументы);// или (C ++ 11):Фу а{аргументы};
Фу а = новый Фу();// объявляет, что это ссылка на новый объект Foo// инициализируется конструктором по умолчанию// Другой конструктор можно использовать какФу а = новый Фу(аргументы);
Фу б = а;// копирует содержимое a в новый объект Foo b;// альтернативный синтаксис: "Foo b (a)"
// Foo b = a;// объявил бы b ссылкой на объект, на который указывает aФу б = а.клон();// копирует содержимое объекта, на который указывает // к новому объекту Foo;// устанавливает ссылку b, указывающую на этот новый объект;// класс Foo должен реализовывать интерфейс Cloneable// для компиляции этого кода
а.Икс = 5; // модифицирует объект a
а.Икс = 5; // изменяет объект, на который ссылается
стандартное::cout << б.Икс << стандартное::конец;// выводит 0, потому что b равно// какой-то объект кроме
Система.вне.println(б.Икс);// выводит 0, потому что b указывает на// какой-то объект кроме
Фу *c;// объявляет c как указатель на// Объект Foo (изначально// не определено; может указывать куда угодно)
Фу c;// объявляет c как ссылку на Foo// объект (изначально null, если c является членом класса;// перед использованием необходимо инициализировать c// если это локальная переменная)
c = новый Фу;// c устанавливается в значение адреса объекта Foo, созданного оператором new
c = новый Фу();// связывает c для ссылки на новый объект Foo
Фу &d = *c;// связывает d для ссылки на тот же объект, на который указывает c
Фу d = c;// связывает d для ссылки на тот же объект, что и c
c->Икс = 5;// изменяет объект, на который указывает c
c.Икс = 5;// изменяет объект, на который ссылается c
d.бар(5);  // вызывает Foo :: bar () дляc->бар(5); // вызывает Foo :: bar () для * c
d.бар(5); // вызывает Foo.bar () дляc.бар(5); // вызывает Foo.bar () для c
стандартное::cout << d.Икс << стандартное::конец;// выводит 5, потому что d ссылается на// тот же объект, на который указывает c
Система.вне.println(d.Икс);// выводит 5, потому что d ссылается на// тот же объект, что и c
  • В C ++ можно объявить указатель или ссылку на const объект, чтобы предотвратить его изменение клиентским кодом. Функции и методы также могут гарантировать, что они не будут изменять объект, на который указывает указатель, с помощью ключевого слова «const». Это заставляет const-правильность.
  • В Java, по большей части, константная корректность должна полагаться на семантику интерфейса класса, то есть она не строго соблюдается, за исключением общедоступных членов данных, которые помечены окончательный.
C ++Ява
const Фу *а; // изменить объект невозможно              // указывается через aФу * const а = новый Фу; // Объявление константного указателя:// можно изменить объект,// но указатель будет постоянно указывать// к назначенному здесь объекту
окончательный Фу а; // объявление "последней" ссылки:             // можно изменить объект,              // но ссылка будет постоянно указывать              // к первому назначенному ему объекту
а = новый Фу();
а = новый Фу(); // Только в конструкторе
а->Икс = 5;// НЕЗАКОННО
а.Икс = 5;// ЛЕГАЛЬНО, члены объекта все еще могут быть изменены // если явно не объявлено final в объявляющем классе
Фу *const б = новый Фу();// объявление "константного" указателя
окончательный Фу б = новый Фу();// объявление "последней" ссылки
б = новый Фу();// НЕЗАКОННО, его нельзя привязать заново
б = новый Фу();// НЕЗАКОННО, его нельзя привязать заново
б->Икс = 5;// ЮРИДИЧЕСКИЙ, объект все еще можно изменить
б.Икс = 5;// ЮРИДИЧЕСКИЙ, объект все еще можно изменить
  • C ++ поддерживает перейти к заявления, которые могут привести к код спагетти программирование. За исключением оператора goto (который очень редко встречается в реальном коде и крайне не рекомендуется), как Java, так и C ++ имеют в основном одинаковые поток управления структуры, предназначенные для обеспечения соблюдения структурированный поток управления, и полагается на сломать и продолжить заявления, чтобы предоставить некоторые перейти к-подобные функции. Некоторые комментаторы отмечают, что эти помеченные операторы управления потоком нарушают свойство единой точки выхода структурного программирования.[5]
  • C ++ предоставляет низкоуровневые функции, которых нет в Java. В C ++ указатели могут использоваться для управления определенными ячейками памяти, задача, необходимая для написания низкоуровневых Операционная система компоненты. Точно так же многие компиляторы C ++ поддерживают встроенный ассемблер. Код на языке ассемблера можно импортировать в программу C и наоборот. Это делает язык Си еще быстрее. В Java такой код должен находиться во внешних библиотеках, и к нему можно получить доступ только через Собственный интерфейс Java, со значительными накладными расходами на каждый вызов.

Семантика

  • C ++ допускает значения по умолчанию для аргументов функции / метода. В Java нет. Однако, перегрузка метода может использоваться для получения аналогичных результатов в Java, но для создания избыточного кода-заглушки.
  • Минимум кода, необходимого для компиляции для C ++, - это функция, для Java - это класс.
  • C ++ допускает ряд неявных преобразований между собственными типами (включая некоторые сужающие преобразования), а также позволяет определять неявные преобразования с использованием типов, определенных пользователем. В Java неявными являются только расширяющиеся преобразования между собственными типами; другие преобразования требуют явного синтаксиса приведения.
    • В результате, хотя условия цикла (если, в то время как и условие выхода в для) в Java и C ++ ожидают логического выражения, такого как если (a = 5) вызовет ошибку компиляции в Java, потому что не существует неявного сужающего преобразования из int в логическое значение, но будет компилироваться на C ++. Это удобно, если в коде была опечатка и если (а == 5) был предназначен. Однако современные компиляторы C ++ обычно генерируют предупреждение, когда такое присвоение выполняется в условном выражении. Аналогично, автономные сравнительные операторы, например а == 5;, без побочного эффекта обычно приводят к предупреждению.
  • Для передачи параметров функциям C ++ поддерживает как проход по ссылке и передача по стоимости. В Java примитивные параметры всегда передаются по значению. Типы классов, типы интерфейсов и типы массивов все вместе называются ссылочными типами в Java и также всегда передаются по значению.[6][7][8]
  • Встроенные типы Java имеют указанный размер и диапазон, определенный спецификацией языка. В C ++ для встроенных типов определен минимальный диапазон значений, но точное представление (количество битов) можно сопоставить с любыми родными типами, которые предпочтительны на данной платформе.
    • Например, символы Java 16-битные. Unicode символы, а строки состоят из последовательности таких символов. C ++ предлагает как узкие, так и широкие символы, но фактический размер каждого зависит от платформы, как и используемый набор символов. Струны могут быть любого типа.
    • Это также означает, что компиляторы C ++ могут автоматически выбирать наиболее эффективное представление для целевой платформы (т. Е. 64-битные целые числа для 64-битной платформы), в то время как представление фиксировано в Java, то есть значения могут быть сохранены в меньшем -эффективный размер или должен заполнить оставшиеся биты и добавить код для имитации поведения с уменьшенной шириной.
  • Округление и точность значений с плавающей запятой и операций в C ++ определяется реализацией (хотя только очень экзотические или старые платформы отклоняются от IEEE 754 стандарт). Java предоставляет необязательный строгая модель с плавающей запятой (strictfp ), что гарантирует более согласованные результаты на разных платформах, хотя возможно за счет снижения производительности во время выполнения. Однако Java не соответствует строго стандарту IEEE 754. Большинство компиляторов C ++ по умолчанию частично соответствуют IEEE 754 (обычно исключают строгие правила округления и вызывают исключения для результатов NaN), но предоставляют варианты соответствия различной строгости, чтобы обеспечить некоторую оптимизацию.[9][10] Если мы обозначим эти варианты от наименее совместимых до наиболее совместимых как быстрый, последовательный (Java strictfp), близкий к IEEE, и строго-IEEE, мы можем сказать, что большинство реализаций C ++ по умолчанию близкий к IEEE, с возможностью переключения на быстрый или строго-IEEE, а Java по умолчанию быстрый с возможностью переключения на последовательный.
  • В C ++ указатели можно манипулировать непосредственно как значениями адресов памяти. Ссылки Java - это указатели на объекты.[11] Ссылки Java не разрешают прямой доступ к адресам памяти или позволяют манипулировать адресами памяти с помощью арифметики указателей. В C ++ можно создавать указатели на указатели, указатели на целые и двойные числа и указатели на произвольные ячейки памяти. Ссылки Java обращаются только к объектам, но не к примитивам, другим ссылкам или произвольным ячейкам памяти.
  • В C ++ указатели могут указывать на функции или функции-члены (указатели на функции ). Эквивалентный механизм в Java использует ссылки на объекты или интерфейсы.
  • Через выделенные стеком объекты C ++ поддерживает ограниченное управление ресурсами, метод, используемый для автоматического управления памятью и другими системными ресурсами, который поддерживает детерминированное уничтожение объектов. В то время как управление ресурсами в C ++ не может быть гарантировано (даже объекты с соответствующими деструкторами могут быть выделены с помощью новый и оставлен без удаления), он обеспечивает эффективное средство управления ресурсами. Общими ресурсами можно управлять с помощью shared_ptr, вместе с weak_ptr чтобы разбить циклические ссылки. Java поддерживает автоматическое управление памятью с помощью вывоз мусора который может освобождать недостижимые объекты даже при наличии циклических ссылок, но другие системные ресурсы (файлы, потоки, окна, коммуникационные порты, потоки и т. д.) должны быть явно освобождены, потому что сборка мусора не гарантируется сразу после последней ссылки на объект заброшен.
  • Функции C ++, определяемые пользователем перегрузка оператора. Перегрузка операторов позволяет определяемым пользователем типам поддерживать операторы (арифметические, сравнения и т. Д.), Такие как примитивные типы, через определяемые пользователем реализации этих операторов. Обычно рекомендуется сохранять семантику операторов. Java не поддерживает никаких форм перегрузки операторов (хотя в ее библиотеке для конкатенации строк используется оператор сложения).
  • Стандартные функции Java интерфейс прикладного программирования (API) поддержка для отражение и динамическая загрузка произвольного нового кода.
  • C ++ поддерживает статическое и динамическое связывание двоичных файлов.
  • Java имеет дженерики, основная цель которого - предоставлять безопасные по типу контейнеры. C ++ имеет время компиляции шаблоны, которые обеспечивают более широкую поддержку общего программирования и метапрограммирования. Java имеет аннотации, которые позволяют добавлять произвольные пользовательские метаданные в классы и метапрограммировать через инструмент обработки аннотаций.
  • И Java, и C ++ различают собственные типы (также называемые фундаментальный или встроенный типы) и определяемые пользователем типы (также называемые соединение типы). В Java собственные типы имеют только семантику значений, а составные типы имеют только ссылочную семантику. В C ++ все типы имеют семантику значений, но можно создать ссылку на любой тип, что позволит манипулировать объектом с помощью семантики ссылки.
  • C ++ поддерживает множественное наследование произвольных классов. В Java класс может быть производным только от одного класса, но класс может реализовывать несколько интерфейсы (другими словами, он поддерживает множественное наследование типов, но только одиночное наследование реализации).
  • Java явно различает интерфейсы и классы. В C ++ множественное наследование и чисто виртуальные функции позволяют определять классы, которые работают почти так же, как интерфейсы Java, с небольшими отличиями.
  • Java поддерживает как язык, так и стандартную библиотеку для многопоточность. В синхронизированный ключевое слово в Java обеспечивает простой и безопасный мьютексные блокировки для поддержки многопоточных приложений. Java также предоставляет надежные и сложные библиотеки для более продвинутой многопоточной синхронизации. Только с C ++ 11 существует ли определенная модель памяти для многопоточности в C ++ и поддержка библиотеки для создания потоков и многих синхронизирующих примитивов. Для этого также существует множество сторонних библиотек.
  • Функции-члены C ++ могут быть объявлены как виртуальные функции, что означает, что вызываемый метод определяется типом объекта во время выполнения (также известный как динамическая диспетчеризация). По умолчанию методы в C ++ не являются виртуальными (т. Е. подписаться на виртуальный). В Java методы по умолчанию являются виртуальными, но их можно сделать не виртуальными с помощью окончательный ключевое слово (т. е. отказаться виртуальный).
  • Перечисления C ++ являются примитивными типами и поддерживают неявное преобразование в целочисленные типы (но не из целочисленных типов). Перечисления Java могут быть общедоступное статическое перечисление {enumName1, enumName2} и используются как классы. Другой способ - создать другой класс, расширяющий java.lang.Enum ) и поэтому может определять конструкторы, поля и методы как любой другой класс. По состоянию на C ++ 11, C ++ также поддерживает строго типизированные перечисления которые обеспечивают большую безопасность типов и явную спецификацию типа хранилища.
  • Унарные операторы '++' и '-': в C ++ "Операнд должен быть изменяемым lvalue. [пропущено] Результат - обновленный операнд; это lvalue ... ",[12] но в Java "двоичное числовое преобразование, упомянутое выше, может включать преобразование распаковки и преобразование набора значений. При необходимости преобразование набора значений {и / или [...] преобразование упаковки} применяется к сумме до того, как она будет сохранена в переменной . ",[13] т.е. в Java, после инициализации "Integer i = 2;", "++ i;" изменяет ссылку i, назначая новый объект, в то время как в C ++ объект остается прежним.

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

  • Java предлагает автоматические вывоз мусора, которые при определенных обстоятельствах можно обойти через Java в реальном времени Технические характеристики. Управление памятью в C ++ обычно осуществляется с помощью конструкторов, деструкторов и умные указатели. Стандарт C ++ разрешает сборку мусора, но не требует этого. Сборка мусора на практике применяется редко.
  • C ++ может выделять произвольные блоки памяти. Java выделяет память только через создание экземпляров объекта. Произвольные блоки памяти могут быть выделены в Java как массив байтов.
  • Java и C ++ используют разные идиомы для управления ресурсами. Java в основном полагается на сборку мусора, которая может освободить память, в то время как C ++ полагается в основном на Приобретение ресурсов - это инициализация (RAII) идиома. Это отражено в нескольких различиях между двумя языками:
    • В C ++ принято выделять объекты составных типов как локальные переменные, привязанные к стеку, которые уничтожаются, когда они выходят за пределы области видимости. В Java составные типы всегда выделяются в куче и собираются сборщиком мусора (за исключением виртуальных машин, которые используют анализ побега чтобы преобразовать выделение кучи в выделение стека).
    • В C ++ есть деструкторы, а в Java финализаторы. Оба вызываются перед освобождением объекта, но они значительно отличаются. Деструктор объекта C ++ должен вызываться неявно (в случае переменных, привязанных к стеку) или явно для освобождения объекта. Деструктор выполняет синхронно непосредственно перед точкой в ​​программе, в которой объект освобождается. Таким образом, синхронная, скоординированная деинициализация и освобождение в C ++ удовлетворяет идиоме RAII. В Java освобождение объекта неявно обрабатывается сборщиком мусора. Вызывается финализатор объекта Java асинхронно некоторое время после последнего обращения к нему и до того, как он будет освобожден. Очень немногие объекты нуждаются в финализаторах. Финализатор нужен только объектам, которые должны гарантировать некоторую очистку состояния объекта перед освобождением, обычно освобождая ресурсы, внешние по отношению к JVM.
    • С RAII в C ++ один тип ресурса обычно заключен в небольшой класс, который выделяет ресурс при создании и освобождает ресурс при уничтожении и предоставляет доступ к ресурсу между этими точками. Любой класс, который содержит только такие объекты RAII, не нуждается в определении деструктора, поскольку деструкторы объектов RAII вызываются автоматически при уничтожении объекта этого класса. В Java безопасное синхронное освобождение ресурсов может выполняться детерминированно с помощью конструкции try / catch / finally.
    • В C ++ возможно наличие висячий указатель, несвежий Справка объекту, который уже был освобожден. Попытка использовать висящий указатель обычно приводит к сбою программы. В Java сборщик мусора не уничтожает объект, на который имеется ссылка.
    • В C ++ возможны неинициализированные примитивные объекты. Java выполняет инициализацию по умолчанию.
    • В C ++ можно иметь выделенный объект, на который нет действительной ссылки. Такой недостижимый объект не может быть уничтожен (освобожден) и приводит к утечка памяти. Напротив, в Java объект не будет освобожден сборщиком мусора. до тех пор он становится недоступным (для пользовательской программы). (Слабые ссылки поддерживаются, которые работают со сборщиком мусора Java, чтобы разрешить различные сильные стороны Сборка мусора в Java предотвращает многие утечки памяти, но утечки все же возможны при некоторых обстоятельствах.[14][15][16]

Библиотеки

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

Время выполнения

C ++Ява
C ++ скомпилирован непосредственно в Машинный код который затем выполняется непосредственно центральное процессорное устройство.Java скомпилирована в байт-код который Виртуальная машина Java (JVM) тогда интерпретирует во время выполнения. Фактические реализации Java делают своевременная компиляция в собственный машинный код. В качестве альтернативы Компилятор GNU для Java может компилироваться непосредственно в машинный код.
  • Благодаря неограниченной выразительности, низкоуровневые функции языка C ++ (например, неконтролируемый доступ к массиву, необработанные указатели, набирать текст ) нельзя надежно проверить во время компиляции или без дополнительных затрат во время выполнения. Связанные ошибки программирования могут привести к низкоуровневому переполнение буфера и ошибки сегментации. В Стандартная библиотека шаблонов предоставляет высокоуровневые абстракции RAII (например, вектор, список и карту), чтобы помочь избежать таких ошибок. В Java ошибки низкого уровня либо не могут возникать, либо обнаруживаются Виртуальная машина Java (JVM) и сообщается приложению в виде исключение.
  • Язык Java требует определенного поведения в случае доступа к массиву за пределами допустимого диапазона, что обычно требует проверка границ доступов к массиву. Это устраняет возможный источник нестабильности, но обычно за счет замедления выполнения. В некоторых случаях, особенно после Java 7, анализ компилятора может доказать ненужность проверки границ и устранить ее. C ++ не имеет требуемого поведения для доступа за пределы собственных массивов, поэтому не требует проверки границ для собственных массивов. Однако коллекции стандартной библиотеки C ++, такие как std :: vector, предлагают дополнительную проверку границ. Таким образом, массивы Java «обычно безопасны; слегка ограничены; часто имеют накладные расходы», в то время как собственные массивы C ++ «имеют необязательные накладные расходы; немного неограниченны; возможно, небезопасны».

Шаблоны против дженериков

И C ++, и Java предоставляют возможности для общее программирование, шаблоны и дженерики соответственно. Хотя они были созданы для решения аналогичных задач и имеют похожий синтаксис, они совершенно разные.

C ++ шаблоныДженерики Java
Классы, функции, псевдонимы[17] и переменные[18] можно создать по шаблону.Классы и методы могут быть обобщенными.
Параметры могут быть вариативными, любого типа, целочисленного значения, символьного литерала или шаблона класса.Параметры могут быть любого ссылочного типа, включая примитивные типы в штучной упаковке (например, Integer, Boolean ...).
При компиляции для каждого набора параметров будут созданы отдельные экземпляры класса или функции. Для шаблонов классов будут созданы экземпляры только используемых функций-членов.Компилируется одна версия класса или функции, работает для всех параметров типа (через стирание типа).
Объекты шаблона класса, экземпляры которого созданы с разными параметрами, будут иметь разные типы во время выполнения (т. Е. Отдельные экземпляры шаблона являются отдельными классами).Параметры типа стираются при компиляции; объекты класса с разными параметрами типа являются одним и тем же типом во время выполнения. Это вызывает другой конструктор. Из-за стирания этого типа невозможно перегрузить методы, используя различные экземпляры универсального класса.
Реализация шаблона класса или функции должна быть видна в единице перевода, чтобы ее можно было использовать. Обычно это подразумевает наличие определений в файлах заголовков или включение в файл заголовков. По состоянию на C ++ 11, можно использовать шаблоны extern разделить компиляцию некоторых экземпляров.Для использования достаточно подписи класса или функции из скомпилированного файла класса.
Шаблоны могут быть специализированный - для отдельного параметра шаблона может быть предусмотрена отдельная реализация.Дженерики не могут быть специализированными.
Параметры шаблона могут иметь аргументы по умолчанию. ПредварительноC ++ 11, это было разрешено только для шаблонных классов, но не для функций.Параметры универсального типа не могут иметь аргументы по умолчанию.
Подстановочные знаки не поддерживаются. Вместо этого возвращаемые типы часто доступны как вложенные typedefs. (Также, C ++ 11 добавлено ключевое слово авто, который действует как подстановочный знак для любого типа, который может быть определен во время компиляции.)Подстановочные знаки поддерживаются как параметр типа.
Нет прямой поддержки ограничения параметров типа, но метапрограммирование обеспечивает это[19]Поддерживает ограничение параметров типа с помощью «extends» и «super» для верхней и нижней границ соответственно; позволяет установить отношения между параметрами типа.
Разрешает создание объекта с типом типа параметра.Исключает создание экземпляра объекта с типом типа параметра (кроме отражения).
Параметр типа шаблона класса может использоваться для статических методов и переменных.Параметр типа универсального класса нельзя использовать для статических методов и переменных.
Статические переменные не разделяется между классами и функциями с параметрами разных типов.Статические переменные совместно используются экземплярами классов с разными параметрами типа.
Шаблоны классов и функций не устанавливают отношения типов для параметров типа в своем объявлении. Использование неверного параметра типа приводит к сбою компиляции, часто генерируя сообщение об ошибке в коде шаблона, а не в коде пользователя, который его вызывает. Правильное использование шаблонных классов и функций зависит от надлежащей документации. Метапрограммирование предоставляет эти функции за счет дополнительных усилий. Было предложение решить эту проблему в C ++ 11, так называемые Концепции, это планируется в следующем стандарте.Универсальные классы и функции могут устанавливать отношения типов для параметров типа в своем объявлении. Использование неверного параметра типа приводит к ошибке типа в коде, который его использует. Операции с параметризованными типами в универсальном коде разрешены только способами, безопасность которых может быть гарантирована объявлением. Это приводит к большей безопасности типов за счет гибкости.
Шаблоны Полный по Тьюрингу (увидеть метапрограммирование шаблона ).Обобщения также полны по Тьюрингу[20]

Разное

  • Java и C ++ используют разные средства для разделения кода на несколько исходных файлов. Java использует систему пакетов, которая определяет имя файла и путь для всех определений программ. Его компилятор импортирует исполняемый файл файлы классов. C ++ использует заголовочный файл исходный код система включения для обмена объявлениями между исходными файлами.
  • Скомпилированные файлы кода Java обычно меньше файлов кода в C ++, поскольку Байт-код Java обычно более компактный, чем родной Машинный код и программы Java никогда не связываются статически.
  • Компиляция C ++ имеет добавленный текстовый предварительная обработка фазы, а Java - нет. Таким образом, некоторые пользователи добавляют фазу предварительной обработки в свой процесс сборки для лучшей поддержки условной компиляции.
  • Операторы деления и модуля Java четко определены для усечения до нуля. C ++ (предварительноC ++ 11 ) не указывает, усекают ли эти операторы до нуля или «усекают до бесконечности». -3/2 всегда будет -1 в Java и C ++ 11, но С ++ 03 компилятор может возвращать -1 или -2, в зависимости от платформы. C99 определяет деление так же, как Java и C ++ 11. Оба языка гарантируют (где a и b - целые типы), что (а / б) * б + (а% б) == а для всех a и b (b! = 0). В С ++ 03 версия иногда будет быстрее, так как можно выбрать любой режим усечения, свойственный процессору.
  • Размеры целочисленных типов определены в Java (int - 32-битный, long - 64-битный), а в C ++ размер целых чисел и указателей равен компилятору и двоичный интерфейс приложения (ABI) зависит от заданных ограничений. Таким образом, программа на Java будет иметь согласованное поведение на разных платформах, тогда как программа на C ++ может потребовать адаптации для некоторых платформ, но может работать быстрее с более естественными целочисленными размерами для локальной платформы.

Пример сравнения C ++ и Ява существует в Викиучебники.

Спектакль

Помимо выполнения скомпилированной программы Java, компьютеры, на которых выполняются приложения Java, обычно также должны запускать Виртуальная машина Java (JVM), а скомпилированные программы на C ++ могут запускаться без внешних приложений. Ранние версии Java значительно уступали по производительности статически компилируемым языкам, таким как C ++. Это связано с тем, что программные операторы этих двух тесно связанных языков могут компилироваться в несколько машинных инструкций с помощью C ++, в то же время компилируясь в несколько байтовых кодов, включающих несколько машинных инструкций, каждая при интерпретации JVM. Например:

Оператор Java / C ++Сгенерированный код C ++ (x86)Сгенерированный Java байт-код
вектор [i] ++;
mov edx,[ebp+]mov eax,[ebp+]inc dword ptr [edx+eax*4]
aload_1iload_2dup2ialoadiconst_1iaddiastore

Поскольку оптимизация производительности - очень сложный вопрос, очень сложно количественно оценить разницу в производительности между C ++ и Java в общих чертах, а большинство тестов ненадежны и необъективны. Учитывая очень разную природу языков, также трудно провести четкие качественные различия. Короче говоря, в Java есть неотъемлемая неэффективность и жесткие ограничения, поскольку она в значительной степени полагается на гибкие высокоуровневые абстракции, однако использование мощного JIT-компилятора (как в современных реализациях JVM) может смягчить некоторые проблемы. В любом случае, если неэффективность Java слишком велика, скомпилированный код C или C ++ может быть вызван из Java через JNI.

Некоторые недостатки, присущие языку Java, включают, в основном:

  • Все объекты размещены в куче. Несмотря на то, что в современных JVM выделение выполняется очень быстро с использованием «выпуклого выделения», которое работает аналогично выделению стека, производительность все равно может быть снижена из-за вызова сборщика мусора. Современные JIT-компиляторы в некоторой степени смягчают эту проблему с помощью анализа перехода или обнаружения перехода для выделения некоторых объектов в стеке, поскольку Oracle JDK 6.
  • В проектах, критичных к производительности, таких как эффективные системы баз данных и библиотеки обмена сообщениями, приходилось использовать внутренние неофициальные API, такие как sun.misc.Unsafe получить доступ к ручному управлению ресурсами и уметь делать выделение стека; эффективное управление псевдо-указателями.
  • Даже при использовании стандартных контейнеров требуется большое количество приведений во время выполнения, что снижает производительность. Однако большинство этих приведений статически исключаются JIT-компилятором.
  • Гарантии безопасности обходятся недешево. Например, компилятор должен поставить в код соответствующие проверки диапазона. Защита каждого доступа к массиву с помощью проверки диапазона неэффективна, поэтому большинство JIT-компиляторов попытаются устранить их статически или вывести их из внутренних циклов (хотя большинство собственных компиляторов для C ++ будут делать то же самое, когда необязательно используются проверки диапазона).
  • Отсутствие доступа к низкоуровневым деталям не позволяет разработчику улучшить программу там, где компилятор не может этого сделать.[21]
  • Обязательное использование ссылочной семантики для всех определяемых пользователем типов в Java может привести к большим объемам избыточных косвенных обращений (или переходов) к памяти (если их не исключил JIT-компилятор), что может привести к частым пропускам кеш-памяти (a.k.a. обработка кеша ). Кроме того, оптимизация кеша, обычно через кеш-память или не обращающий внимания на тайник структуры данных и алгоритмы, часто могут приводить к повышению производительности на порядки, а также к предотвращению вырождения временной сложности, которое характерно для многих алгоритмов пессимизации кеша и, следовательно, является одной из наиболее важных форм оптимизации; Ссылочная семантика, как предписано в Java, делает такую ​​оптимизацию невозможной на практике (ни программистом, ни JIT-компилятором).
  • Вывоз мусора,[22] поскольку эта форма автоматического управления памятью вводит накладные расходы на память.[23]

Тем не менее, у дизайна Java есть ряд преимуществ, некоторые из которых реализованы, а некоторые только теоретически:

  • Ява вывоз мусора может иметь лучшую согласованность кеша, чем обычное использование маллок /новый для выделения памяти. Тем не менее аргументы существуют[ласковые слова ] что оба распределителя одинаково фрагментируют кучу и ни один из них не демонстрирует лучшую локальность кеша. Однако в C ++ выделение отдельных объектов в куче происходит редко, и большие количества отдельных объектов обычно выделяются блоками через контейнер STL и / или с помощью небольшого распределителя объектов.[24][25]
  • Компиляция во время выполнения потенциально может использовать информацию о платформе, на которой выполняется код, для более эффективного улучшения кода. Однако большинство современных компиляторов (C, C ++ и т. Д.) Генерируют несколько путей кода, чтобы использовать все вычислительные возможности данной системы.[26] Кроме того, можно сделать обратный аргумент, что собственные компиляторы могут лучше использовать оптимизацию для конкретной архитектуры и наборы инструкций, чем многоплатформенные дистрибутивы JVM.
  • Компиляция во время выполнения позволяет более агрессивно встраивать виртуальные функции, чем это возможно для статического компилятора, потому что JIT-компилятор имеет больше информации обо всех возможных целях виртуальных вызовов, даже если они находятся в разных динамически загружаемых модулях. Доступные в настоящее время реализации JVM не имеют проблем с встраиванием большинства мономорфных, в основном мономорфных и диморфных вызовов, и в настоящее время ведутся исследования по встроенным также мегаморфным вызовам благодаря недавним динамическим улучшениям вызова, добавленным в Java 7.[27] Встраивание может позволить дальнейшую оптимизацию, такую ​​как векторизация цикла или разворачивание петли, что привело к огромному увеличению общей производительности.
  • В Java синхронизация потоков встроена в язык, поэтому JIT-компилятор потенциально может с помощью анализа выхода снимать блокировки,[28] значительно повысить производительность наивного многопоточного кода.

Также некоторые проблемы с производительностью возникают в C ++:

  • Разрешение указателям указывать на любой адрес может затруднить оптимизацию из-за возможности сглаживание указателя.
  • Поскольку код, сгенерированный из различных экземпляров одного и того же шаблона класса в C ++, не является общим (как с универсальными шаблонами со стиранием типов в Java), чрезмерное использование шаблонов может привести к значительному увеличению размера исполняемого кода (раздувание кода ). Однако, поскольку шаблоны функций агрессивно встроены, они иногда могут уменьшить размер кода, но, что более важно, позволяют компилятору проводить более агрессивный статический анализ и оптимизацию кода, что чаще делает их более эффективными, чем код без шаблонов. Напротив, универсальные Java-шаблоны менее эффективны, чем универсальный код.
  • Поскольку в традиционном компиляторе C ++ динамическое связывание выполняется после генерации кода и оптимизации в C ++, вызовы функций, охватывающие различные динамические модули, не могут быть встроены. Однако современные компиляторы C ++, такие как MSVC и Clang + LLVM, предлагают параметры генерации кода во время компоновки, которые позволяют компилировать модули в промежуточные форматы, что позволяет встраивать их на финальном этапе компоновки.

Официальный стандарт и справочник языка

Спецификация языка

Язык C ++ определяется ISO / IEC 14882, ISO стандарт, опубликованный ISO / IEC JTC1 / SC22 / WG21 комитет. Последний проект стандарта после стандартизации C ++ 17 также доступен.[29]

Язык C ++ развивается через открытый руководящий комитет, называемый Комитетом по стандартам C ++. Комитет состоит из создателя C ++. Бьярне Страуструп, организатор Херб Саттер, а также другие выдающиеся личности, в том числе многие представители отраслей и групп пользователей (т. е. заинтересованных сторон). Поскольку комитет является открытым, любой может свободно присоединяться к нему, участвовать и вносить предложения по предстоящим выпускам стандарта и технических спецификаций. В настоящее время комитет стремится выпускать новый стандарт каждые несколько лет, хотя в прошлом строгие процессы проверки и обсуждения означали более длительные задержки между публикацией новых стандартов (1998, 2003 и 2011).

Язык Java определяется Спецификация языка Java,[30] книга, изданная Oracle.

Язык Java постоянно развивается посредством процесса, называемого Процесс сообщества Java, а мировое сообщество программистов представлено группой людей и организаций - членов сообщества Java[31]- который активно участвует в улучшении языка, отправляя публичные запросы - запросы на спецификацию Java, - которые должны пройти официальную и публичную проверку, прежде чем они будут интегрированы в язык.

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

Товарные знаки

«C ++» не является товарным знаком какой-либо компании или организации и не принадлежит никому.[32]"Java" является товарным знаком Корпорация Oracle.[33]

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

  1. ^ «API беззнаковой целочисленной арифметики теперь в JDK 8».
  2. ^ "Учебники по Java: передача информации методу или конструктору". Oracle. Получено 17 февраля 2013.
  3. ^ «Учебники по Java: объект как суперкласс». Oracle. Получено 17 февраля 2013..
  4. ^ «Программное обеспечение XMPP» Библиотеки ». xmpp.org. Получено 13 июн 2013.
  5. ^ Роберт К. Мартин (январь 1997 г.). «Java против C ++: критическое сравнение» (PDF). Архивировано из оригинал (PDF) 11 мая 2008 г.. Получено 15 декабря 2007.
  6. ^ «Типы ссылок и значения». Спецификация языка Java, третье издание. Получено 9 декабря 2010.
  7. ^ Хорстманн, Кей; Корнелл, Гэри (2008). Ядро Java. я (Восьмое изд.). Sun Microsystems. С. 140–141. ISBN  978-0-13-235476-9. Некоторые программисты (и, к сожалению, даже некоторые авторы книг) утверждают, что в языке программирования Java для объектов используется вызов по ссылке. Однако это неверно. Поскольку это такое распространенное заблуждение, стоит рассмотреть контрпример более подробно ... Это обсуждение демонстрирует, что язык программирования Java не использует вызов по ссылке для объектов. Вместо ссылки на объекты передаются по значению.
  8. ^ Дейтель, Пол; Дейтель, Харви (2009). Java для программистов. Прентис Холл. п. 223. ISBN  978-0-13-700129-3. В отличие от некоторых других языков, Java не позволяет программистам выбирать передачу по значению или по ссылке - все аргументы передаются по значению. Вызов метода может передавать в метод два типа значений - копии примитивных значений (например, значения типа int и double) и копии ссылок на объекты (включая ссылки на массивы). Сами объекты нельзя передавать методам.
  9. ^ «Семантика математики с плавающей запятой в GCC». Фонд GNU. Получено 20 апреля 2013.
  10. ^ "Компилятор Microsoft c ++, / fp (указание поведения с плавающей запятой)". Корпорация Майкрософт. Получено 19 марта 2013.
  11. ^ «Спецификация языка Java 4.3.1: объекты». Sun Microsystems. Получено 9 декабря 2010.
  12. ^ Стандарт языка программирования C ++ '11, 5.3.2 Увеличение и уменьшение [expr.pre.incr].
  13. ^ Спецификация языка Java ™, Java SE 7 Edition, главы 15.14.2, 15.14.3, 15.15.1, 15.15.2, http://docs.oracle.com/javase/specs/
  14. ^ Сатиш Чандра Гупта, Раджив Паланки (16 августа 2005 г.). «Утечки памяти Java - поймайте меня, если сможете». IBM DeveloperWorks. Архивировано из оригинал 22 июля 2012 г.. Получено 2 апреля 2015.CS1 maint: использует параметр авторов (ссылка на сайт)
  15. ^ Как исправить утечку памяти в Java Велько Крунич (10 марта, 2009)
  16. ^ Создание утечки памяти с помощью Java на переполнение стека.com
  17. ^ http://en.cppreference.com/w/cpp/language/type_alias
  18. ^ http://en.cppreference.com/w/cpp/language/variable_template
  19. ^ Библиотека признаков типа Boost
  20. ^ Обобщения Java завершены по Тьюрингу
  21. ^ Кларк, Натан; Амир Хормати; Сами Йехиа; Скотт Малке (2007). «Liquid SIMD: абстрагирование оборудования SIMD с использованием облегченного динамического отображения». Hpca'07: 216–227.
  22. ^ Хундт, Роберт (27 апреля 2011 г.). «Распознавание циклов в C ++ / Java / Go / Scala» (PDF; 318 kB). Стэнфорд, Калифорния: Дни Скала 2011. Получено 17 ноября 2012. Java показывает большой компонент GC, но хорошую производительность кода. [...] Мы обнаружили, что в отношении производительности C ++ с большим отрывом выигрывает. [...] Версия Java была, вероятно, самой простой для реализации, но трудной для анализа производительности. В частности, эффекты, связанные со сборкой мусора, были сложными и их очень трудно настроить.
  23. ^ Мэтью Герц, Эмери Д. Бергер (2005). «Количественная оценка производительности сборки мусора по сравнению с явным управлением памятью» (PDF). OOPSLA 2005. Архивировано с оригинал (PDF) 6 июля 2017 г.. Получено 15 марта 2015. В частности, когда сборка мусора имеет в пять раз больше памяти, чем требуется, ее производительность во время выполнения соответствует или немного превышает производительность явного управления памятью. Однако производительность сборки мусора существенно снижается, когда необходимо использовать кучи меньшего размера. С трехкратным объемом памяти он работает в среднем на 17% медленнее, а с вдвое большим объемом памяти он работает на 70% медленнее.
  24. ^ Александреску, Андрей (2001). Эддисон-Уэсли (ред.). Современный дизайн C ++: применение общих шаблонов программирования и проектирования. Глава 4. С. 77–96. ISBN  978-0-201-70431-0.
  25. ^ «Библиотека Boost Pool». Увеличение. Получено 19 апреля 2013.
  26. ^ Ориентация на процессоры архитектуры IA-32 для проверки производительности во время выполнения[постоянная мертвая ссылка ]
  27. ^ Устранение «проблемы» встраивания доктором Клиффом. Click | Azul Systems: Блоги
  28. ^ Oracle Technology Network для разработчиков Java
  29. ^ «Рабочий проект стандарта языка программирования C ++» (PDF).
  30. ^ Спецификация языка Java
  31. ^ Программа Java Community Process (SM) - Участие - члены JCP
  32. ^ Часто задаваемые вопросы Бьярна Страуструпа: у вас есть C ++?
  33. ^ ZDNet: Oracle покупает Sun; Теперь владеет Java.

внешние ссылки