Введение

Сравнение двух языков программирования

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

Цели проектирования

Различия между языками программирования C++ и Java можно проследить в их происхождении, поскольку у них разные цели проектирования. C++ был разработан для системного и прикладного программирования (т.е. инфраструктурного программирования), расширяя процедурный язык программирования C, который был разработан для эффективного выполнения. К C, C++ добавил поддержку объектно-ориентированного программирования, обработки исключений, управления ресурсами на основе времени жизни (Resource Acquisition Is Initialization (RAII)), обобщенного программирования, метапрограммирования шаблонов и стандартной библиотеки C++, включающей обобщенные контейнеры и алгоритмы (библиотеку стандартных шаблонов или STL), а также множество других средств общего назначения. Java — это универсальный, параллельный, основанный на классах, объектно-ориентированный язык программирования, предназначенный для минимизации зависимостей от реализации. Он полагается на виртуальную машину Java для обеспечения безопасности и высокой переносимости. Он поставляется с обширной библиотекой, предназначенной для абстрагирования базовой платформы. Java — это язык со статической типизацией, объектно-ориентированный, использующий синтаксис, похожий на (но несовместимый с) C++. Он включает в себя систему документации Javadoc. Различные цели разработки C++ и Java привели к различным принципам и компромиссам в проектировании этих языков. Различия следующие:

C++ | Java
------- | --------
Расширяет C поддержкой объектно-ориентированного и обобщенного программирования. Код на C может быть использован наиболее корректно. | Сильно подвержен влиянию синтаксиса C++/C.
Совместим с исходным кодом C, за исключением некоторых особых случаев. | Совместим с исходным кодом C, за исключением нескольких краевых случаев.
Предоставляет Java Native Interface и, недавно, Java Native Access для прямого вызова кода C/C++. Однако, нативные языки небезопасны, и приложения, использующие нативные методы, подвержены повреждению памяти. Если код написан небрежно, нативные методы могут снизить производительность системы, поскольку сборщик мусора не может контролировать или обслуживать использование нативной памяти, а переключение контекста между нативным и ненативным кодом требует затрат. | Напишите один раз, компилируйте где угодно (WOCA). Напишите один раз, запускайте везде (WORA/WORE).
Позволяет процедурное, функциональное, объектно-ориентированное, обобщенное программирование и метапрограммирование шаблонов. Поддерживает смешение парадигм. | Разрешает процедурное программирование, функциональное программирование (с Java 8) и обобщенное программирование (с Java 5), но настоятельно рекомендует объектно-ориентированную парадигму.
Включает поддержку создания языков сценариев. |
Выполняется как нативный исполняемый машинный код для целевого набора инструкций. | Выполняется на виртуальной машине.
Предоставляет типы объектов и имена типов. |
Позволяет отражение через информацию о типе времени выполнения (RTTI). | Рефлексивен, позволяя метапрограммирование и динамическое генерирование кода во время выполнения.
Имеет несколько стандартов двоичной совместимости (обычно Microsoft (для компилятора MSVC) и Itanium/GNU (для почти всех остальных компиляторов)). | Имеет один стандарт двоичной совместимости, кросс-платформенный для ОС и компилятора.
Необязательная автоматическая проверка границ (например, метод `at` в контейнерах `vector` и `string`). | Все операции должны быть проверены на границы всеми совместимыми дистрибутивами Java. HotSpot может удалить проверку границ.
Нативная поддержка беззнаковой арифметики. | Отсутствует нативная поддержка беззнаковой арифметики. Java 8 изменяет некоторые аспекты, но детали неясны.
Стандартные минимальные пределы для всех числовых типов, но фактические размеры определяются реализацией. Стандартные типы доступны через стандартную библиотеку `<cstdint>`. | Стандартизированные пределы и размеры всех примитивных типов на всех платформах.
Поддерживаются указатели, ссылки и передача по значению для всех типов (примитивных или пользовательских). | Все типы (примитивные и ссылочные) всегда передаются по значению.
Управление памятью может осуществляться вручную через `new`/`delete`, автоматически по области видимости или с помощью умных указателей. Поддерживает детерминированное уничтожение объектов. | Автоматический сбор мусора.
Стандарт ABI сборки мусора в C++11, хотя компиляторы не обязаны реализовывать сборку мусора. | Поддерживает недетерминированный метод `finalize`, использование которого не рекомендуется.
Управление ресурсами может осуществляться вручную или автоматически на основе времени жизни (RAII). | Управление ресурсами обычно должно осуществляться вручную или автоматически с помощью финализаторов, хотя это обычно не рекомендуется.
Имеет `try-with-resources` для автоматического управления ресурсами на основе области видимости (начиная с версии 7). Также может быть выполнено с использованием внутреннего API `sun.misc.Unsafe`, но такое использование настоятельно не рекомендуется и будет заменено общедоступным API в будущей версии Java. |
Поддерживает классы, структуры (типы пассивных данных (PDS)) и объединения, и может выделять их в куче или в стеке. | Классы выделяются в куче. Java SE 6 оптимизирует с помощью анализа экранирования для выделения некоторых объектов в стеке.
Позволяет явно переопределять типы и некоторые неявные сужающие преобразования (для совместимости с C). | Жесткая типобезопасность, за исключением расширяющих преобразований.
Стандартная библиотека C++ была разработана с ограниченной областью применения и функциями, но включает поддержку языка, диагностику, общие утилиты, строки, локали, контейнеры, алгоритмы, итераторы, числовые методы, ввод/вывод, генераторы случайных чисел, разбор регулярных выражений, средства многопоточности, признаки типов (для статической интроспекции типов) и стандартную библиотеку C. Библиотека Boost предлагает больше функций, включая сетевой ввод/вывод. | Богатый набор сторонних библиотек существует для графического интерфейса пользователя и других функций, таких как: Adaptive Communication Environment (ACE), Crypto++, различные библиотеки обмена мгновенными сообщениями (IM) XMPP, OpenLDAP, Qt, gtkmm.
Стандартная библиотека расширялась с каждой версией. К версии 1.6 библиотека включала поддержку локалей, ведения журналов, контейнеров и итераторов, алгоритмов, программирования графического интерфейса пользователя (но не с использованием системного графического интерфейса пользователя), графики, многопоточности, сети, безопасности платформы, интроспекции, динамической загрузки классов, блокирующего и неблокирующего ввода/вывода. Она предоставляла интерфейсы или вспомогательные классы для XML, XSLT, MIDI, подключения к базам данных, служб именования (например, LDAP), криптографии, служб безопасности (например, Kerberos), служб печати и веб-служб. SWT предлагал абстракцию для графических интерфейсов пользователя, специфичных для платформы, но был заменен JavaFX в последних версиях, обеспечивая ускорение графики и темы оформления CSS. Хотя он не поддерживает поддержку "родного внешнего вида платформы". |
Перегрузка операторов для большинства операторов. Сохранение значения (семантики) настоятельно рекомендуется. | Операторы не могут быть перегружены. Язык переопределяет `+` и `+=` для класса `String`.
Одиночное и множественное наследование классов, включая виртуальное наследование. | Поддерживает только одиночное наследование классов.
Шаблонные вычисления во время компиляции. |
Позволяет выполнять метапрограммирование, полное по Тьюрингу. | Обобщения используются для достижения базовой параметризации типов, но они не транслируются из исходного кода в байт-код из-за использования стирания типов компилятором.
Указатели на функции, функциональные объекты, лямбда-выражения (в C++11) и интерфейсы (с использованием абстрактных классов). | Функциональные ссылки, функциональные объекты и лямбда-выражения были добавлены в Java 8.
Классы (и интерфейсы, которые являются классами) могут передаваться по ссылке через `SomeClass.class` и `someObject.getClass`. |
Отсутствует стандартный механизм встроенной документации. Существуют сторонние инструменты (например, Doxygen). | Обширная стандартная документация Javadoc для всех системных классов и методов.
Ключевое слово `const` для определения неизменяемых переменных и функций-членов, которые не изменяют объект. Неизменяемость распространяется как средство обеспечения корректности кода относительно изменяемости объектов (см. const correctness). | `final` предоставляет версию `const`, эквивалентную указателям `type* const` для объектов и `const` для примитивных типов.
Неизменяемость членов объекта достигается с помощью интерфейсов только для чтения и инкапсуляции объектов. |
Поддерживает оператор `goto`. | Поддерживает метки с циклами и блоками операторов. `goto` является зарезервированным ключевым словом, но помечено как "неиспользуемое" в спецификации Java.

Семантика

C++ допускает значения по умолчанию для аргументов функции/метода. Java этого не поддерживает. Однако, перегрузка методов может быть использована для получения схожих результатов в Java, но приводит к генерации избыточного шаблонного кода. Минимальный код, необходимый для компиляции в C++ – это функция, а в Java – класс. C++ позволяет широкий спектр неявных преобразований между встроенными типами (включая некоторые сужающие преобразования), а также позволяет определять неявные преобразования, включающие пользовательские типы. В Java неявными являются только расширяющие преобразования между встроенными типами; другие преобразования требуют явного приведения типов. В результате, хотя условия циклов (if, while и условие выхода в for) в Java и C++ ожидают булево выражение, код вида `if(a = 5)` вызовет ошибку компиляции в Java, поскольку отсутствует неявное сужающее преобразование из int в boolean, но будет успешно скомпилирован в C++. Это может быть полезно, если в коде допущена опечатка и подразумевалось `if(a == 5)`. Однако, современные компиляторы C++ обычно генерируют предупреждение при выполнении такого присваивания в условном выражении. Аналогично, отдельные операторы сравнения, например `a==5;`, без побочных эффектов, как правило, приводят к предупреждению. Для передачи параметров функциям, C++ поддерживает как передачу по ссылке, так и передачу по значению. В Java примитивные параметры всегда передаются по значению. Типы классов, интерфейсов и массивов коллективно называются ссылочными типами в Java и также всегда передаются по значению. Встроенные типы Java имеют заданный размер и диапазон, определенные спецификацией языка. В C++ минимальный диапазон значений определен для встроенных типов, но точное представление (количество бит) может быть сопоставлено с предпочтительными встроенными типами на данной платформе. Например, символы Java – это 16-битные символы Unicode, а строки состоят из последовательности таких символов. C++ предлагает как узкие, так и широкие символы, но фактический размер каждого из них зависит от платформы, как и используемый набор символов. Строки могут быть сформированы из любого типа. Это также означает, что компиляторы C++ могут автоматически выбирать наиболее эффективное представление для целевой платформы (например, 64-битные целые числа для 64-битной платформы), в то время как представление фиксировано в Java, что означает, что значения могут быть либо сохранены в менее эффективном размере, либо необходимо дополнять оставшиеся биты и добавлять код для эмуляции поведения с уменьшенной шириной. Округление и точность значений с плавающей точкой и операций в C++ определяются реализацией (хотя только очень экзотические или устаревшие платформы отклоняются от стандарта IEEE 754). Java предоставляет необязательную строгую модель с плавающей точкой (strictfp), которая гарантирует более согласованные результаты на разных платформах, хотя и за счет возможного снижения производительности во время выполнения. Однако Java не полностью соответствует стандарту IEEE 754. Большинство компиляторов C++ по умолчанию частично соответствуют IEEE 754 (обычно исключая строгие правила округления и генерируя исключения при результатах NaN), но предоставляют опции соответствия различной строгости, чтобы обеспечить некоторую оптимизацию. Если обозначить эти опции от наименее совместимых к наиболее совместимым как быстрые, согласованные (Java's strictfp), близкие к IEEE и строгие IEEE, можно сказать, что большинство реализаций C++ по умолчанию близки к IEEE, с возможностью переключения на быстрые или строгие IEEE, в то время как Java по умолчанию использует быстрые с возможностью переключения на согласованные. В C++ указателями можно манипулировать напрямую как значениями адресов памяти. Ссылки Java – это указатели на объекты. Ссылки Java не позволяют прямого доступа к адресам памяти или манипулирования адресами памяти с помощью арифметики указателей. В C++ можно создавать указатели на указатели, указатели на int и double, а также указатели на произвольные места в памяти. Ссылки Java получают доступ только к объектам, никогда к примитивам, другим ссылкам или произвольным местам в памяти. В Java память может быть прочитана и записана произвольными значениями с помощью API `sun.misc.Unsafe`, однако он устарел и не рекомендуется к использованию. В C++ указатели могут указывать на функции или методы класса (указатели на функции). Эквивалентный механизм в Java использует ссылки на объекты или интерфейсы. С помощью объектов, выделенных в стеке, C++ поддерживает управление ресурсами на основе области видимости, технику, используемую для автоматического управления памятью и другими системными ресурсами, обеспечивающую детерминированное уничтожение объектов. Хотя управление ресурсами на основе области видимости в C++ не может быть гарантировано (даже объекты с корректными деструкторами могут быть выделены с помощью `new` и оставлены без удаления), оно обеспечивает эффективный способ управления ресурсами. Общие ресурсы могут управляться с помощью `shared_ptr`, а также `weak_ptr` для разрыва циклических ссылок. Java поддерживает автоматическое управление памятью с помощью сборщика мусора, который может освобождать недостижимые объекты даже при наличии циклических ссылок, но другие системные ресурсы (файлы, потоки, окна, порты связи, потоки и т.д.) должны быть явно освобождены, поскольку сборка мусора не гарантируется произойти сразу после того, как последняя ссылка на объект будет отброшена. C++ поддерживает перегрузку операторов, определяемых пользователем. Перегрузка операторов позволяет пользовательским типам поддерживать операторы (арифметические, сравнения и т.д.) как встроенные типы посредством пользовательских реализаций этих операторов. Обычно рекомендуется сохранять семантику операторов. Java не поддерживает перегрузку операторов (хотя ее библиотека использует оператор сложения для конкатенации строк). Java предоставляет стандартную поддержку API для рефлексивного программирования (reflection) и динамической загрузки произвольного нового кода. C++ поддерживает статическую и динамическую компоновку двоичных файлов. Java имеет обобщения (generics), основная цель которых – предоставление типобезопасных контейнеров. C++ имеет шаблоны времени компиляции (compile-time templates), которые обеспечивают более широкую поддержку обобщенного программирования и метапрограммирования. Java имеет аннотации, которые позволяют добавлять произвольные пользовательские метаданные к классам и метапрограммирование с помощью инструмента обработки аннотаций. И Java, и C++ различают встроенные типы (также называемые фундаментальными или базовыми типами) и пользовательские типы (также называемые составными типами). В Java встроенные типы имеют только семантику значения, а составные типы – только семантику ссылки. В C++ все типы имеют семантику значения, но для любого типа можно создать ссылку, которая позволит манипулировать объектом с помощью семантики ссылки. C++ поддерживает множественное наследование произвольных классов. В Java класс может наследовать только от одного класса, но класс может реализовывать несколько интерфейсов (другими словами, он поддерживает множественное наследование типов, но только единичное наследование реализации). Java явно различает интерфейсы и классы. В C++ множественное наследование и виртуальные функции позволяют определять классы, которые функционируют почти как интерфейсы Java, с некоторыми небольшими различиями. Java имеет поддержку многопоточности как на уровне языка, так и стандартной библиотеки. Ключевое слово `synchronized` в Java предоставляет мьютексы для поддержки многопоточных приложений. Java также предоставляет библиотеки для более продвинутой синхронизации многопоточности. C++11 имеет определенную модель памяти для многопоточности в C++ и поддержку библиотек для создания потоков и многих примитивов синхронизации. Существует также множество сторонних библиотек для этого. Методы класса C++ могут быть объявлены как виртуальные, что означает, что метод, который будет вызван, определяется типом объекта во время выполнения (также известный как динамическая диспетчеризация). По умолчанию методы в C++ не являются виртуальными (т.е. включение виртуальности выполняется явно). В Java методы являются виртуальными по умолчанию, но могут быть сделаны не виртуальными с помощью ключевого слова `final` (т.е. отключение виртуальности выполняется явно). Перечисления C++ являются примитивными типами и поддерживают неявное преобразование в целочисленные типы (но не из целочисленных типов). Перечисления Java могут быть объявлены как `public static enum{enumName1,enumName2}` и используются как классы. Другой способ – создать другой класс, который расширяет `java.lang.Enum<E>` и, следовательно, может определять конструкторы, поля и методы, как и любой другой класс. Начиная с C++11, C++ поддерживает строго...

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

Java предлагает автоматическую сборку мусора, которую можно обойти в определенных обстоятельствах с помощью спецификации Real Time Java. Управление памятью в C++ обычно осуществляется через конструкторы, деструкторы и умные указатели. Стандарт C++ допускает сборку мусора, но не требует ее. На практике сборка мусора используется редко. C++ может выделять произвольные блоки памяти. Java выделяет память только при создании объектов. В Java произвольные блоки памяти могут быть выделены в виде массива байтов. Java и C++ используют различные идиомы для управления ресурсами. Java в основном полагается на сборку мусора, которая может освободить память, в то время как C++ в основном полагается на идиому Resource Acquisition Is Initialization (RAII). Это отражается в нескольких различиях между двумя языками: в C++ обычно выделяют объекты составных типов как локальные переменные, связанные со стеком, которые уничтожаются при выходе из области видимости. В Java составные типы всегда выделяются в куче и собираются сборщиком мусора (за исключением виртуальных машин, использующих анализ экранирования для преобразования выделений в куче в выделения в стеке). В C++ есть деструкторы, а в Java – финализаторы. Оба вызываются перед освобождением объекта, но существенно отличаются. Деструктор объекта C++ должен вызываться неявно (в случае переменных, связанных со стеком) или явно для освобождения объекта. Деструктор выполняется синхронно непосредственно перед точкой в программе, в которой объект освобождается. Синхронное, скоординированное прекращение инициализации и освобождение в C++ таким образом соответствуют идиоме RAII. Деструкторы в C++ – это нормальный способ возврата ресурсов, связанных с объектом, и являются необходимой противоположностью конструкторов. В Java освобождение объектов обрабатывается неявно сборщиком мусора. Финализатор объекта Java вызывается асинхронно через некоторое время после последнего доступа к нему и перед его освобождением. Очень немногим объектам нужны финализаторы. Финализатор необходим только для объектов, которые должны гарантировать некоторую очистку состояния объекта перед освобождением, обычно освобождая ресурсы, внешние для JVM. Прямое использование финализаторов обычно не рекомендуется, поскольку они непредсказуемы, обычно опасны и в большинстве случаев не нужны. Следует избегать рассмотрения финализаторов как аналогов деструкторов C++. Скорее, конструкция try-with-resources или блок try-finally достигают более схожей цели. Одна из проблем с финализаторами или очистителями заключается в том, что нет гарантии их немедленного выполнения. Следовательно, финализатор никогда не следует использовать для задач, критичных ко времени. Кроме того, финализаторы приводят к серьезным штрафам производительности и значительно увеличивают время, необходимое для освобождения объектов, поэтому их использование не рекомендуется и устарело в Java 9. При использовании RAII в C++ один тип ресурса обычно оборачивается в небольшой класс, который выделяет ресурс при создании и освобождает его при уничтожении, обеспечивая доступ к ресурсу между этими моментами. Любой класс, содержащий только такие объекты RAII, не нуждается в определении деструктора, поскольку деструкторы объектов RAII вызываются автоматически при уничтожении объекта этого класса. В Java безопасное синхронное освобождение ресурсов можно выполнить детерминированно с помощью конструкции try-catch-finally. В качестве альтернативы, конструкция try-with-resources, представленная в Java 7, должна использоваться вместо конструкции try-finally. Конструкция try-with-resources более лаконична и удобочитаема. Она также предоставляет более полезную диагностическую информацию, поскольку подавленные исключения не отбрасываются и будут напечатаны в трассировке стека с указанием того, что они были подавлены. В C++ возможен висячий указатель – устаревшая ссылка на объект, который уже был освобожден. Попытка использовать висячий указатель обычно приводит к сбою программы. В Java сборщик мусора не уничтожает объект, на который есть ссылка. В C++ возможны неинициализированные примитивные объекты. Java обеспечивает инициализацию по умолчанию. В C++ возможен выделенный объект, к которому нет действительной ссылки. Такой недоступный объект не может быть уничтожен (освобожден), что приводит к утечке памяти. В отличие от этого, в Java объект не будет освобожден сборщиком мусора, пока он не станет недоступным (из пользовательской программы). (Поддерживаются слабые ссылки, которые работают со сборщиком мусора Java, чтобы обеспечить различные уровни доступности). Сборка мусора в Java предотвращает многие утечки памяти, но утечки все же возможны в определенных обстоятельствах. Автоматический сборщик мусора может создать ложное впечатление, что в Java не нужно думать об управлении памятью. Однако это не совсем так. В широком смысле, это связано с тем, что программа может иметь «утечки памяти», более формально известные как «непреднамеренное удержание объектов». Примером утечки памяти может быть программа, написанная без логических ошибок, за исключением того, что она не удалила устаревшие ссылки. Это приводит к более высокой активности сборщика мусора, большему объему используемой памяти. В крайних случаях эта проблема может привести к ошибке OutOfMemoryError, но это случается редко. Решением является обнуление ссылок на объекты. Вторая распространенная причина утечек памяти – использование кэша, который больше не актуален. Решением для утечек памяти, вызванных использованием устаревшего кэша, является представление кэша с помощью WeakHashMap.

Библиотеки

C++ предоставляет кроссплатформенный доступ ко многим функциям, которые обычно доступны в библиотеках, специфичных для платформы. Прямой доступ из Java к функциям операционной системы и аппаратному обеспечению требует использования Java Native Interface (JNI).

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

C++ Java C++ компилируется непосредственно в машинный код, который затем выполняется непосредственно центральным процессором. Java компилируется в байт-код, который виртуальная машина Java (JVM) интерпретирует во время выполнения. Реальные реализации Java используют JIT-компиляцию (компиляцию "на лету") в машинный код. Из-за своей неограниченной выразительности, низкоуровневые возможности языка C++ (например, неконтролируемый доступ к массивам, "сырые" указатели, приведение типов) не могут быть надёжно проверены во время компиляции или без дополнительных затрат во время выполнения. Ошибки программирования, связанные с этим, могут приводить к переполнению буфера и ошибкам сегментации. Стандартная библиотека шаблонов предоставляет абстракции RAII более высокого уровня (например, vector, list и map), чтобы помочь избежать подобных ошибок. В Java низкоуровневые ошибки либо не могут возникнуть, либо обнаруживаются виртуальной машиной Java (JVM) и сообщаются приложению в виде исключения. Язык Java требует определённого поведения при обращении к массиву за его пределами, что обычно подразумевает проверку границ доступа к массиву. Это устраняет потенциальный источник нестабильности, но обычно за счёт снижения производительности. В некоторых случаях, особенно начиная с Java 7, анализ компилятора может доказать ненужность проверки границ и исключить её. В C++ не определено поведение при обращении к нативным массивам за их пределами, поэтому проверка границ для них не требуется. Однако коллекции стандартной библиотеки C++, такие как std::vector, предлагают опциональную проверку границ. В итоге, массивы Java – "обычно безопасны, немного ограничены, часто имеют накладные расходы", а нативные массивы C++ – "имеют опциональные накладные расходы, немного не ограничены, потенциально небезопасны".

Разное

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

Языковые спецификации

Язык C++ определяется стандартом ISO/IEC 14882, опубликованным комитетом ISO/IEC JTC1/SC22/WG21. Также доступен последний, пост-стандартизационный проект C++17. Развитие языка C++ осуществляется посредством открытого руководящего комитета, называемого Комитетом по стандартам C++. В состав комитета входят создатель C++ Бьярне Строуструп, председатель Герб Саттер и другие известные специалисты, включая многочисленных представителей индустрии и пользовательских групп (то есть заинтересованных сторон). Будучи открытым комитетом, любой желающий может присоединиться к его работе, участвовать в обсуждениях и вносить предложения для будущих версий стандарта и технических спецификаций. В настоящее время комитет стремится выпускать новый стандарт каждые несколько лет, хотя в прошлом строгие процедуры рассмотрения и обсуждения приводили к более длительным задержкам между публикациями новых стандартов (1998, 2003 и 2011 годов). Язык Java определяется спецификацией языка Java – книгой, издаваемой компанией Oracle. Язык Java непрерывно развивается посредством процесса, называемого Java Community Process, а мировое сообщество программистов представлено группой людей и организаций – членами Java Community, которые активно участвуют в совершенствовании языка, направляя публичные запросы (Java Specification Requests), которые должны пройти формальную и публичную экспертизу, прежде чем будут включены в язык. Отсутствие чёткого стандарта для Java и несколько более неустойчивый характер его спецификаций постоянно подвергаются критике со стороны заинтересованных сторон, стремящихся к большей стабильности и консервативности при добавлении новых функций языка и библиотек. В отличие от этого, комитет C++ также постоянно подвергается критике, но по противоположной причине – за излишнюю строгость и консерватизм, а также за длительные сроки выпуска новых версий.

Торговые марки

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