Сравнение Java и C++
![]() | В этой статье есть несколько проблем. Пожалуйста, помогите улучшить его или обсудите эти проблемы на странице обсуждения . ( Узнайте, как и когда удалять эти шаблонные сообщения )
|
Java и C++ — два известных объектно-ориентированных языка программирования . По многим показателям популярности языков эти два языка доминировали в объектно-ориентированной и высокопроизводительной разработке программного обеспечения на протяжении большей части 21 века, и их часто напрямую сравнивают и противопоставляют. Синтаксис Java был основан на C/C++ .
Цели дизайна
[ редактировать ]Различия между языками программирования C++ и Java можно объяснить их наследием , поскольку они преследуют разные цели проектирования.
C++ был разработан для программирования систем и приложений (т. е. инфраструктурного программирования), расширяя программирования процедурный язык C , который был разработан для эффективного выполнения. В C++ добавлена поддержка объектно-ориентированного программирования , обработки исключений , управления ресурсами на основе жизненного цикла ( Resource Acquisition Is Initialization (RAII)), универсального программирования , метапрограммирования шаблонов и стандартной библиотеки C++ , которая включает в себя общие контейнеры и алгоритмы ( стандарт Библиотека шаблонов (STL) и многие другие средства общего назначения.
Java — это универсальная, конкурентная, объектно-ориентированная среда на основе классов. [ 1 ] язык программирования, предназначенный для минимизации зависимостей реализации. он использует виртуальную машину Java Для обеспечения безопасности и высокой портативности . Он поставляется с обширной библиотекой, предназначенной для абстракции базовой платформы. Java — это статически типизированный объектно-ориентированный язык, использующий синтаксис, аналогичный (но несовместимый с) C++. Он включает в себя систему документации под названием Javadoc .
Различные цели разработки C++ и Java привели к разным принципам и компромиссам при проектировании между языками. Различия заключаются в следующем:
С++ | Ява |
---|---|
Расширяет C и объектно-ориентированным программированием обобщенным программированием . Код C может быть наиболее правильно использован. | Сильное влияние синтаксиса C++/C. |
Совместим с исходным кодом C , за исключением нескольких крайних случаев . | Предоставляет собственный интерфейс Java и недавно созданный доступ к Java как способ прямого вызова кода C/C++. Однако родные языки небезопасны, а приложения, использующие собственные методы, подвержены повреждению памяти. [ 2 ] Если код написан неаккуратно, собственные методы могут снизить производительность системы, поскольку сборщик мусора не способен отслеживать или поддерживать использование собственной памяти, а переключение контекста между собственным и неродным кодом требует затрат. [ 2 ] |
Напишите один раз, компилируйте где угодно (WOCA). | Напишите один раз, бегите куда угодно /везде (WORA/WORE). |
Позволяет процедурное программирование , функциональное программирование , объектно-ориентированное программирование , обобщенное программирование и метапрограммирование шаблонов . Предпочитает сочетание парадигм. | Позволяет процедурное программирование , функциональное программирование (начиная с Java 8) и обобщенное программирование (начиная с Java 5), но настоятельно поощряет парадигму объектно-ориентированного программирования . Включает поддержку создания языков сценариев . |
Запускается как собственный исполняемый машинный код для целевого набора команд . | Запускается на виртуальной машине . |
Предоставляет типы объектов и имена типов. Позволяет отражение через информацию о типе времени выполнения (RTTI). | Является рефлексивным, что позволяет метапрограммировать и генерировать динамический код во время выполнения. |
Имеет несколько стандартов двоичной совместимости (обычно Microsoft (для компилятора MSVC) и Itanium/GNU (почти для всех других компиляторов)). | Имеет один стандарт бинарной совместимости, кроссплатформенный для ОС и компилятора. |
Дополнительная автоматическая проверка границ (например, at() метод в vector и string контейнеры).
|
Все операции должны проверяться всеми совместимыми дистрибутивами Java. HotSpot может убрать проверку границ. |
Встроенная поддержка беззнаковых арифметических операций . | Собственная беззнаковая арифметика не поддерживается. Java 8 кое-что меняет, но некоторые аспекты неясны. [ 3 ] |
Стандартизированные минимальные пределы для всех числовых типов, но фактические размеры определяются реализацией. Стандартизированные типы доступны через стандартную библиотеку. <cstdint> .
|
Стандартизированные пределы и размеры всех типов примитивов на всех платформах. |
Указатели, ссылки и передача по значению поддерживаются для всех типов (примитивных или определяемых пользователем). | Все типы (примитивные и ссылочные типы ) всегда передаются по значению. [ 4 ] |
Управление памятью может осуществляться вручную через new / delete , автоматически по области или с помощью интеллектуальных указателей. Поддерживает детерминированное уничтожение объектов. Сбор мусора ABI стандартизирован в C++11, хотя компиляторы не обязаны реализовывать сбор мусора.
|
Автоматический сбор мусора . [ 5 ] Поддерживает недетерминированный метод Finalize(), использование которого не рекомендуется. [ 6 ] [ 7 ] |
Управление ресурсами может осуществляться вручную или посредством автоматического управления ресурсами на основе срока службы ( RAII ). | Управление ресурсами обычно должно осуществляться вручную или автоматически с помощью финализаторов, хотя обычно это не рекомендуется. Имеет try-with-resources для автоматического управления ресурсами на основе области (версия 7 и более поздние).
Это также можно сделать с помощью внутреннего API. |
Поддерживает классы, структуры ( типы пассивных структур данных (PDS)) и объединения и может размещать их в куче или стеке . | Классы размещаются в куче . Java SE 6 оптимизируется с помощью escape-анализа для выделения некоторых объектов в стеке . |
Позволяет явно переопределять типы и некоторые неявные сужающие преобразования (для совместимости с C). | Жесткая безопасность типа, за исключением расширяющих преобразований. |
Стандартная библиотека C ++ была разработана с ограниченным объемом и функциями, но включает языковую поддержку, диагностику, общие утилиты, строки, локали, контейнеры, алгоритмы, итераторы , числовые значения, ввод/вывод, генераторы случайных чисел, анализ регулярных выражений, средства многопоточности. , свойства типов (для статического анализа типов) и стандартная библиотека C. Библиотека Boost предлагает больше функций, включая сетевой ввод-вывод.
Существует большое количество сторонних библиотек для графического пользовательского интерфейса и других функций, таких как: Adaptive Communication Environment (ACE), Crypto++ , различные XMPP библиотеки мгновенного обмена сообщениями (IM), [ 8 ] OpenLDAP , Qt , gtkmm . |
Стандартная библиотека расширялась с каждым выпуском. В версии 1.6 библиотека включала поддержку локалей, ведения журналов, контейнеров и итераторов, алгоритмов, программирования с графическим интерфейсом (но не с использованием системного графического интерфейса), графики, многопоточности, работы в сети, безопасности платформы, самоанализа, динамической загрузки классов, блокировки и -блокировка ввода/вывода. Он предоставлял интерфейсы или классы поддержки для XML , XSLT , MIDI , подключения к базе данных, служб именования (например, LDAP ), криптографии, служб безопасности (например, Kerberos ), служб печати и веб-служб. его заменил JavaFX SWT предлагал абстракцию для графических интерфейсов пользователя, специфичных для платформы, но в последних выпусках ; позволяющее ускорение графики и пользовательский интерфейс с CSS-темами. Хотя он не поддерживает никакой поддержки «собственного вида платформы». |
Перегрузка операторов для большинства операторов. Настоятельно рекомендуется сохранять значение (семантику). | Операторы не являются переопределяемыми. Язык переопределяет + и += для класса String. |
Одиночное и множественное наследование классов, включая виртуальное наследование. | Поддерживается только одиночное наследование классов. [ 1 ] |
Шаблоны времени компиляции. Позволяет осуществить полное метапрограммирование по Тьюрингу. | Обобщенные шаблоны используются для достижения базовой параметризации типов, но они не преобразуются из исходного кода в байтовый код из-за использования стирания типов компилятором . |
Указатели функций, объекты функций, лямбда-выражения (в C++11 ) и интерфейсы (с использованием абстрактных классов). | Ссылки на функции, объекты функций и лямбды были добавлены в Java 8 . Классы (и интерфейсы, которые являются классами) также могут передаваться как ссылки через SomeClass.class и someObject.getClass() .
|
Нет стандартного встроенного механизма документации. Существует стороннее программное обеспечение (например, Doxygen ). | Обширный стандарт документации Javadoc для всех системных классов и методов. |
const Ключевое слово для определения неизменяемых переменных и функций-членов, которые не изменяют объект. Константность распространяется как средство обеспечения во время компиляции корректности кода в отношении изменчивости объектов (см. const-correctness ).
|
final предоставляет версию const , [ 9 ] эквивалентно type* const указатели на объекты и const для примитивных типов. Неизменяемость членов объекта достигается с помощью интерфейсов только для чтения и инкапсуляции объектов.
|
Поддерживает goto заявление.
|
Поддерживает метки с циклами и блоками операторов. goto является зарезервированным ключевым словом, но в спецификации Java помечено как «неиспользуемое» .
|
Исходный код может быть написан как кроссплатформенный (может быть скомпилирован для BSD , GNU/Linux , macOS , Solaris , Windows и т. д. без изменений) и написан с использованием функций, специфичных для платформы. Обычно компилируется в собственный машинный код и должен быть перекомпилирован для каждой целевой платформы. | Скомпилирован в байт-код Java для JVM . Байт-код зависит от платформы Java, но обычно не зависит от конкретных функций операционной системы . |
Особенности языка
[ редактировать ]Синтаксис
[ редактировать ]- Синтаксис Java имеет контекстно-свободную грамматику , которую можно анализировать простым парсером LALR . Анализ C++ более сложен. Например,
Foo<1>(3);
представляет собой последовательность сравнений, если Foo является переменной, но создает объект, если Foo является именем шаблона класса. - C++ допускает константы, переменные и функции уровня пространства имен. В Java такие сущности должны принадлежать к некоторому заданному типу и, следовательно, должны быть определены внутри определения типа, либо класса, либо интерфейса .
- В C++ объекты являются значениями, а в Java — нет. использует семантику значений C++ по умолчанию , тогда как Java всегда использует ссылочную семантику . Чтобы выбрать ссылочную семантику в C++, можно использовать либо указатель, либо ссылку.
С++ | Ява |
---|---|
class Foo { // Declares class Foo
int x = 0; // Private Member variable. It will
// be initialized to 0, if the
// constructor would not set it.
// (from C++11)
public:
Foo() : x(0) // Constructor for Foo; initializes
{} // x to 0. If the initializer were
// omitted, the variable would
// be initialized to the value that
// has been given at declaration of x.
int bar(int i) { // Member function bar()
return 3*i + x;
}
};
|
class Foo { // Defines class Foo
private int x; // Member variable, normally declared
// as private to enforce encapsulation
// initialized to 0 by default
public Foo() { // Constructor for Foo
} // no-arg constructor supplied by default
public int bar(int i) { // Member method bar()
return 3*i + x;
}
}
|
Foo a;
// declares a to be a Foo object value,
// initialized using the default constructor.
// Another constructor can be used as
Foo a(args);
// or (C++11):
Foo a{args};
|
Foo a = new Foo();
// declares a to be a reference to a new Foo object
// initialized using the default constructor
// Another constructor can be used as
Foo a = new Foo(args);
|
Foo b = a;
// copies the contents of a to a new Foo object b;
// alternative syntax is "Foo b(a)"
|
// Foo b = a;
// would declare b to be reference to the object pointed to by a
Foo b = a.clone();
// copies the contents of the object pointed to by a
// to a new Foo object;
// sets the reference b to point to this new object;
// the Foo class must implement the Cloneable interface
// for this code to compile
|
a.x = 5; // modifies the object a
|
a.x = 5; // modifies the object referenced by a
|
std::cout << b.x << std::endl;
// outputs 0, because b is
// some object other than a
|
System.out.println(b.x);
// outputs 0, because b points to
// some object other than a
|
Foo *c;
// declares c to be a pointer to a
// Foo object (initially
// undefined; could point anywhere)
|
Foo c;
// declares c to be a reference to a Foo
// object (initially null if c is a class member;
// it is necessary to initialize c before use
// if it is a local variable)
|
c = new Foo;
// c is set to the value of the address of the Foo object created by operator new
|
c = new Foo();
// binds c to reference a new Foo object
|
Foo &d = *c;
// binds d to reference the same object to which c points
|
Foo d = c;
// binds d to reference the same object as c
|
c->x = 5;
// modifies the object pointed to by c
|
c.x = 5;
// modifies the object referenced by c
|
d.bar(5); // invokes Foo::bar() for a
c->bar(5); // invokes Foo::bar() for *c
|
d.bar(5); // invokes Foo.bar() for a
c.bar(5); // invokes Foo.bar() for c
|
std::cout << d.x << std::endl;
// outputs 5, because d references the
// same object to which c points
|
System.out.println(d.x);
// outputs 5, because d references the
// same object as c
|
- В C++ можно объявить указатель или ссылку на константный объект, чтобы предотвратить его изменение клиентским кодом. Функции и методы также могут гарантировать, что они не изменят объект, на который указывает указатель, с помощью ключевого слова const. Это обеспечивает константную корректность .
- На Яве
final
ключевое слово похоже наconst
Ключевое слово в C++, но его использование более ограничено. [ 9 ] По большей части константная корректность должна полагаться на семантику интерфейса класса, т. е. она не строго соблюдается, за исключением общедоступных членов данных, которые помечены какfinal
.
С++ | Ява |
---|---|
const Foo *a; // it is not possible to modify the object
// pointed to by a through a
|
final Foo a; // a declaration of a "final" reference:
// it is possible to modify the object,
// but the reference will constantly point
// to the first object assigned to it
|
a = new Foo();
|
a = new Foo(); // Only in constructor
|
a->x = 5;
// ILLEGAL
|
a.x = 5;
// LEGAL, the object's members can still be modified
// unless explicitly declared final in the declaring class
|
Foo *const b = new Foo();
// a declaration of a "const" pointer
// it is possible to modify the object,
// but the pointer will constantly point
// to the object assigned to it here
|
final Foo b = new Foo();
// a declaration of a "final" reference
|
b = new Foo();
// ILLEGAL, it is not allowed to re-bind it
|
b = new Foo();
// ILLEGAL, it is not allowed to re-bind it
|
b->x = 5;
// LEGAL, the object can still be modified
|
b.x = 5;
// LEGAL, the object can still be modified
|
- С++ поддерживает
goto
операторы, которые могут привести к программированию спагетти-кода . За исключением оператора goto (который очень редко встречается в реальном коде и крайне не рекомендуется), и Java, и C++ имеют в основном одинаковые потока управления структуры , предназначенные для обеспечения структурированного потока управления , и полагаются на операторы Break и continue для обеспечения некоторыхgoto
-подобные функции. Некоторые комментаторы отмечают, что эти помеченные операторы управления потоком нарушают свойство единой точки выхода структурного программирования. [ 10 ] - C++ предоставляет возможности низкого уровня, которых в большинстве случаев не хватает в Java (одним заметным исключением является
sun.misc.Unsafe
API для прямого доступа к памяти и манипуляций с ней). В C++ указатели можно использовать для управления определенными участками памяти — задача, необходимая для написания низкоуровневых компонентов операционной системы . Аналогично, многие компиляторы C++ поддерживают встроенный ассемблер . Код языка ассемблера можно импортировать в программу C и наоборот. Это делает язык C еще быстрее. В Java такой код должен находиться во внешних библиотеках, и доступ к нему возможен только через собственный интерфейс Java , что требует значительных затрат на каждый вызов.
Семантика
[ редактировать ]- C++ допускает значения по умолчанию для аргументов функции/метода. Ява этого не делает. Однако перегрузку метода можно использовать для получения аналогичных результатов в Java, но сгенерировать избыточный код-заглушку.
- Минимум кода, необходимый для компиляции для C++, — это функция, для Java — класс.
- C++ допускает ряд неявных преобразований между собственными типами (включая некоторые сужающие преобразования), а также позволяет определять неявные преобразования, включающие определяемые пользователем типы. В Java неявными являются только расширяющие преобразования между собственными типами; другие преобразования требуют явного синтаксиса приведения.
- В результате этого, хотя условия цикла (
if
,while
и условие выхода вfor
) и в Java, и в C++ ожидают логическое выражение, такой код, какif(a = 5)
вызовет ошибку компиляции в Java, поскольку неявное сужающее преобразование из целого числа в логическое отсутствует, но будет компилироваться в C++. Это удобно, если код оказался опечаткой иif(a == 5)
было предназначено. Однако современные компиляторы C++ обычно выдают предупреждение, когда такое присваивание выполняется внутри условного выражения. Аналогично, отдельные операторы сравнения, напримерa==5;
, без побочных эффектов, обычно приводит к предупреждению.
- В результате этого, хотя условия цикла (
- Для передачи параметров функциям C++ поддерживает как передачу по ссылке , так и передачу по значению . В Java примитивные параметры всегда передаются по значению. Типы классов, типы интерфейсов и типы массивов вместе называются ссылочными типами в Java и также всегда передаются по значению. [ 11 ] [ 12 ] [ 13 ]
- Встроенные типы Java имеют определенный размер и диапазон, определенные спецификацией языка. В C++ для встроенных типов определен минимальный диапазон значений, но точное представление (количество битов) может быть сопоставлено с любыми собственными типами, которые являются предпочтительными на данной платформе.
- Например, символы Java — это 16-битные символы Юникода , а строки состоят из последовательности таких символов. C++ предлагает как узкие, так и широкие символы, но фактический размер каждого из них зависит от платформы, как и используемый набор символов. Строки могут быть сформированы из любого типа.
- Это также означает, что компиляторы C++ могут автоматически выбирать наиболее эффективное представление для целевой платформы (т. е. 64-битные целые числа для 64-битной платформы), в то время как представление фиксировано в Java, то есть значения могут храниться либо в менее -эффективный размер, или необходимо дополнить оставшиеся биты и добавить код для эмуляции поведения уменьшенной ширины.
- Округление и точность значений и операций с плавающей запятой в C++ определяются реализацией (хотя только очень экзотические или старые платформы отходят от стандарта IEEE 754 ). Java предоставляет дополнительную строгую модель с плавающей запятой ( strictfp ), которая гарантирует более согласованные результаты на разных платформах, хотя и за счет возможного снижения производительности во время выполнения. Однако Java не соответствует строго стандарту IEEE 754. Большинство компиляторов C++ по умолчанию частично соответствуют стандарту IEEE 754 (обычно исключая строгие правила округления и выдавая исключения для результатов NaN), но предоставляют варианты соответствия различной строгости, чтобы обеспечить некоторую оптимизацию. [ 14 ] [ 15 ] Если мы обозначим эти параметры от наименее совместимого до наиболее совместимого как быстрый , согласованный (Java strictfp ), близкий к IEEE и строгий IEEE , мы можем сказать, что большинство реализаций C++ по умолчанию используют почти IEEE с возможностью переключения на быстрый или строгий режим. -IEEE , тогда как Java по умолчанию использует быстрый режим с возможностью переключения на согласованный .
- В C++ указателями можно манипулировать непосредственно как значениями адресов памяти. Ссылки Java — это указатели на объекты. [ 16 ] Ссылки Java не обеспечивают прямой доступ к адресам памяти и не позволяют манипулировать адресами памяти с помощью арифметики указателей. В C++ можно создавать указатели на указатели, указатели на целые и двойные числа, а также указатели на произвольные ячейки памяти. Ссылки Java обращаются только к объектам, но не к примитивам, другим ссылкам или произвольным областям памяти. В Java память можно читать и записывать произвольными значениями, используя команду
sun.misc.Unsafe
API, однако он устарел и не рекомендуется. - В C++ указатели могут указывать на функции или функции-члены ( указатели на функции ). Эквивалентный механизм в Java использует ссылки на объекты или интерфейсы.
- С помощью объектов, выделенных в стеке, C++ поддерживает управление ресурсами с ограниченной областью — метод, используемый для автоматического управления памятью и другими системными ресурсами, который поддерживает детерминированное уничтожение объектов. Хотя управление ограниченными ресурсами в C++ не может быть гарантировано (даже объекты с соответствующими деструкторами могут быть выделены с помощью
new
и не удален) он обеспечивает эффективное средство управления ресурсами. Общие ресурсы можно управлять с помощьюshared_ptr
, вместе сweak_ptr
разорвать циклические ссылки. Java поддерживает автоматическое управление памятью с помощью сборки мусора. [ 7 ] который может освобождать недоступные объекты даже при наличии циклических ссылок, но другие системные ресурсы (файлы, [ 5 ] потоки, окна, коммуникационные порты, потоки и т. д.) должны быть явно освобождены, поскольку не гарантируется, что сборка мусора произойдет сразу после прекращения последней ссылки на объект. - определяемых пользователем В C++ предусмотрена перегрузка операторов . Перегрузка операторов позволяет определяемым пользователем типам поддерживать операторы (арифметику, сравнения и т. д.), такие как примитивные типы, посредством определяемых пользователем реализаций этих операторов. Обычно рекомендуется сохранять семантику операторов. Java не поддерживает никакую форму перегрузки операторов (хотя ее библиотека использует оператор сложения для объединения строк).
- Java поддерживает стандартный интерфейс прикладного программирования (API) для рефлексивного программирования (отражения) и динамической загрузки произвольного нового кода.
- C++ поддерживает статическое и динамическое связывание двоичных файлов.
- В Java есть дженерики , основная цель которых — предоставить типобезопасные контейнеры. времени компиляции В C++ имеются шаблоны , которые обеспечивают более широкую поддержку универсального программирования и метапрограммирования. В Java есть аннотации , которые позволяют добавлять к классам произвольные пользовательские метаданные и метапрограммировать с помощью инструмента обработки аннотаций .
- И Java, и C++ различают собственные типы (также называемые фундаментальными или встроенными типами) и определяемые пользователем типы (также называемые составными типами). В Java собственные типы имеют только семантику значений, а составные типы имеют только ссылочную семантику. В C++ все типы имеют семантику значений, но ссылку можно создать на любой тип, что позволит манипулировать объектом с помощью семантики ссылок.
- C++ поддерживает множественное наследование произвольных классов. В Java класс может быть производным только от одного класса. [ 1 ] но класс может реализовывать несколько интерфейсов [ 17 ] (другими словами, он поддерживает множественное наследование типов, но только однократное наследование реализации).
- Java явно различает интерфейсы и классы. В C++ множественное наследование и чисто виртуальные функции позволяют определять классы, которые функционируют почти так же, как интерфейсы Java, с некоторыми небольшими отличиями.
- Java поддерживает как язык, так и стандартную библиотеку многопоточности .
synchronized
Ключевое слово в Java обеспечивает блокировки мьютексов для поддержки многопоточных приложений. [ 18 ] [ 19 ] Java также предоставляет библиотеки для более продвинутой многопоточной синхронизации. В C++11 имеется определенная модель памяти для многопоточности в C++, а также поддержка библиотеки для создания потоков и многих примитивов синхронизации. Для этого также существует множество сторонних библиотек. - Функции-члены C++ могут быть объявлены как виртуальные функции , что означает, что вызываемый метод определяется типом объекта во время выполнения (так называемая динамическая диспетчеризация). По умолчанию методы в C++ не являются виртуальными (т. е. разрешены virtual ). В Java методы по умолчанию являются виртуальными, но их можно сделать невиртуальными с помощью
final
ключевое слово (т. е. отказ от виртуального доступа ). - Перечисления C++ являются примитивными типами и поддерживают неявное преобразование в целочисленные типы (но не из целочисленных типов). Перечисления Java могут быть
public static enum{enumName1,enumName2}
и используются как классы. Другой способ — создать еще один класс, расширяющийjava.lang.Enum<E>
) и поэтому может определять конструкторы, поля и методы как любой другой класс. Начиная с C++11 , C++ поддерживает строго типизированные перечисления , которые обеспечивают большую безопасность типов и явное указание типа хранилища. - Унарные операторы '++' и '--': в C++ «Операнд должен быть изменяемым lvalue . [пропущено] Результатом является обновленный операнд; это lvalue...», [ 20 ] но в Java «двоичное числовое продвижение, упомянутое выше, может включать преобразование распаковки и преобразование набора значений. При необходимости преобразование набора значений {и/или [...] преобразование упаковки} применяется к сумме до ее сохранения в переменной .", [ 21 ] т.е. в Java после инициализации "Integer i=2;", "++i;" изменяет ссылку i, присваивая новый объект, тогда как в C++ объект остается прежним.
Управление ресурсами
[ редактировать ]- Java предлагает автоматическую сборку мусора , которую в определенных обстоятельствах можно обойти с помощью спецификации Java реального времени . Управление памятью в C++ обычно осуществляется с помощью конструкторов, деструкторов и интеллектуальных указателей . Стандарт C++ разрешает сбор мусора, но не требует этого. Сбор мусора на практике используется редко.
- C++ может выделять произвольные блоки памяти. Java выделяет память только посредством создания экземпляра объекта. Произвольные блоки памяти могут быть выделены в Java как массив байтов.
- Java и C++ используют разные идиомы для управления ресурсами. Java в основном полагается на сбор мусора, который может освободить память. [ 7 ] в то время как C++ в основном опирается на идиому «Приобретение ресурсов — это инициализация » (RAII). Это отражается в нескольких различиях между двумя языками:
- В C++ принято размещать объекты составных типов как локальные переменные, привязанные к стеку, которые уничтожаются, когда выходят за пределы области видимости. В Java составные типы всегда размещаются в куче и собираются сборщиком мусора (за исключением виртуальных машин, которые используют escape-анализ для преобразования выделений кучи в выделения стека).
- В C++ есть деструкторы, [ 7 ] в то время как в Java есть финализаторы . [ 7 ] Оба вызываются перед освобождением объекта, но они существенно различаются. Деструктор объекта C++ должен вызываться неявно (в случае переменных, привязанных к стеку) или явно для освобождения объекта. Деструктор выполняется синхронно непосредственно перед тем моментом в программе, в котором объект освобождается. Таким образом, синхронная, скоординированная деинициализация и освобождение памяти в C++ удовлетворяет идиоме RAII. Деструкторы в C++ — это обычный способ вернуть ресурсы, связанные с объектом, и необходимый аналог конструкторов. [ 7 ] В Java освобождение объекта неявно обрабатывается сборщиком мусора. Финализатор объекта Java вызывается асинхронно через некоторое время после последнего обращения к нему и до его освобождения. Очень немногие объекты нуждаются в финализаторах. Финализатор необходим только объектам, которые должны гарантировать некоторую очистку состояния объекта перед освобождением, обычно освобождая ресурсы, внешние по отношению к JVM. [ 7 ] Прямое использование финализаторов обычно не рекомендуется, поскольку они непредсказуемы, обычно опасны и в большинстве случаев не нужны. [ 7 ] Следует быть осторожным и не думать о финализаторах как о деструкторах C++. [ 7 ] Скорее, блок try-with-resources или try-finally выполняет ту же задачу, что и деструктор. [ 7 ] Одна из проблем с финализаторами и очистителями заключается в том, что нет гарантии, что они запустятся немедленно. [ 7 ] Следовательно, финализатор никогда не следует использовать для задач, критичных по времени. [ 7 ] Кроме того, финализаторы имеют серьезные потери производительности и значительно увеличивают время, необходимое для освобождения объектов, поэтому их использование не рекомендуется и не рекомендуется в Java 9.
- При использовании RAII в C++ один тип ресурса обычно заключен в небольшой класс, который выделяет ресурс при создании и освобождает ресурс при уничтожении, а также обеспечивает доступ к ресурсу между этими точками. Любому классу, который содержит только такие объекты RAII, не требуется определять деструктор, поскольку деструкторы объектов RAII вызываются автоматически при уничтожении объекта этого класса. В Java безопасное синхронное освобождение ресурсов можно выполнить детерминированно с помощью конструкции try/catch/finally. Альтернативно, вместо конструкции try-finally следует использовать конструкцию try-with-resources, представленную в Java 7. [ 22 ] Конструкция try-with-resources более лаконична и удобочитаема. [ 22 ] Это также предоставляет более полезную диагностическую информацию, поскольку подавленные исключения не отбрасываются и будут напечатаны в трассировке стека с информацией о том, что они были подавлены. [ 22 ]
- В C++ возможно наличие висячего указателя — устаревшей ссылки на объект, который уже был освобожден. Попытка использовать висячий указатель обычно приводит к сбою программы. В Java сборщик мусора не уничтожает объект, на который ссылается.
- В C++ можно иметь неинициализированные примитивные объекты. Java обеспечивает инициализацию по умолчанию.
- В C++ возможно наличие выделенного объекта, на который нет допустимой ссылки. Такой недостижимый объект не может быть уничтожен (освобожден), что приводит к утечке памяти . Напротив, в Java объект не будет освобожден сборщиком мусора до тех пор, пока он не станет недоступным (для пользовательской программы). ( Поддерживаются слабые ссылки , которые работают со сборщиком мусора Java, обеспечивая различную степень достижимости.) Сбор мусора в Java предотвращает многие утечки памяти, но при некоторых обстоятельствах утечки все еще возможны. [ 23 ] [ 24 ] [ 25 ] Автоматический сборщик мусора может создать ложное впечатление, что в Java не нужно думать об управлении памятью. [ 5 ] Однако это не совсем так. [ 5 ] Грубо говоря, это связано с тем, что в программе могут быть «утечки памяти», более формально известные как «непреднамеренное удержание объектов». [ 5 ] Примером утечки памяти, которая может произойти, является программа, написанная без каких-либо логических ошибок, за исключением того, что она не удалила устаревшие ссылки. [ 5 ] Это приводит к более интенсивному использованию сборщика мусора и увеличению объема памяти . [ 5 ] В экстремальных обстоятельствах эта проблема может привести к ошибке OutOfMemoryError, но это случается редко.
[ 5 ] Решением этой проблемы является обнуление ссылок на объекты. [ 5 ] Вторая распространенная причина утечки памяти — использование кэша, который стал неактуальным. Решение проблемы утечек памяти из-за использования старого кеша состоит в том, чтобы представить кеш с помощью WeakHashMap
.
Библиотеки
[ редактировать ]- C++ обеспечивает кросс-платформенный доступ ко многим функциям, обычно доступным в библиотеках для конкретной платформы. Прямой доступ из Java к собственной операционной системе и функциям оборудования требует использования собственного интерфейса Java .
Время выполнения
[ редактировать ]С++ | Ява |
---|---|
C++ компилируется непосредственно в машинный код , который затем выполняется непосредственно центральным процессором . | Java компилируется в байт-код , который виртуальной машиной Java (JVM) затем интерпретируется во время выполнения. Реальные реализации Java выполняют своевременную компиляцию в собственный машинный код. |
- Из-за своей неограниченной выразительности возможности языка C++ низкого уровня (например, непроверяемый доступ к массиву, необработанные указатели, каламбур типов ) не могут быть надежно проверены во время компиляции или без дополнительных затрат во время выполнения. низкого уровня Сопутствующие ошибки программирования могут привести к переполнению буфера и ошибкам сегментации . Стандартная библиотека шаблонов предоставляет абстракции RAII более высокого уровня (такие как вектор, список и карта), чтобы помочь избежать таких ошибок. В Java ошибки низкого уровня либо не могут возникнуть, либо обнаруживаются виртуальной машиной Java (JVM) и сообщаются приложению в виде исключения .
- Язык Java требует особого поведения в случае доступа к массиву за пределами границ, что обычно требует проверки границ доступа к массиву. Это устраняет возможный источник нестабильности, но обычно за счет замедления выполнения. В некоторых случаях, особенно начиная с Java 7, анализ компилятора может доказать ненужность проверки границ и устранить ее. В C++ нет обязательного поведения для доступа к собственным массивам за пределами границ, поэтому не требуется проверка границ для собственных массивов. Однако коллекции стандартных библиотек C++, такие как std::vector, предлагают дополнительную проверку границ. Подводя итог, можно сказать, что массивы Java «обычно безопасны; слегка ограничены; часто имеют накладные расходы», в то время как собственные массивы C++ «имеют необязательные накладные расходы; слегка неограничены; возможно, небезопасны».
Шаблоны против дженериков
[ редактировать ]И C++, и Java предоставляют средства для обобщенного программирования , шаблонов и обобщений соответственно. Хотя они были созданы для решения схожих задач и имеют схожий синтаксис, они совершенно разные.
Шаблоны С++ Дженерики Java Классы, функции, псевдонимы [ 26 ] и переменные [ 27 ] может быть шаблонным. Классы и методы могут быть обобщены. Параметры могут быть переменными, любого типа, целочисленными значениями, символьными литералами или шаблонами классов. Параметры могут быть любого ссылочного типа, включая коробочные примитивные типы (т. е. целое число, логическое значение...). При компиляции для каждого набора параметров будут созданы отдельные экземпляры класса или функции. Для шаблонов классов будут созданы только используемые функции-члены. Компилируется одна версия класса или функции, работает для всех параметров типа (через стирание типа). Объекты шаблона класса, созданные с разными параметрами, будут иметь разные типы во время выполнения (т. е. отдельные экземпляры шаблона являются отдельными классами). Параметры типа стираются при компиляции; объекты класса с параметрами разных типов имеют один и тот же тип во время выполнения. Это вызывает другой конструктор. Из-за этого стирания типа невозможно перегрузить методы, используя разные экземпляры универсального класса. Чтобы можно было использовать реализацию шаблона класса или функции, она должна быть видна внутри единицы перевода. Обычно это подразумевает наличие определений в файлах заголовков или включение в файл заголовков. Начиная с C++11 , можно использовать шаблоны extern для отдельной компиляции некоторых экземпляров. Для его использования достаточно подписи класса или функции из скомпилированного файла класса. Шаблоны могут быть специализированными — для конкретного параметра шаблона может быть предусмотрена отдельная реализация. Дженерики не могут быть специализированными. Параметры шаблона могут иметь аргументы по умолчанию . До C++11 это было разрешено только для классов шаблонов, но не для функций. Параметры универсального типа не могут иметь аргументы по умолчанию. Подстановочные знаки не поддерживаются. Вместо этого возвращаемые типы часто доступны как вложенные определения типов . (Кроме того, в C++11 добавлено ключевое слово auto
, который действует как подстановочный знак для любого типа, который может быть определен во время компиляции.)В качестве параметра типа поддерживаются подстановочные знаки. Ограничение параметров типа и обеспечение связей между параметрами типа эффективно возможны посредством метапрограммирования. [ 28 ] или, начиная с C++20, напрямую через std::derived_from
и другие концепцииПоддерживает ограничение параметров типа с помощью «extends» и «super» для верхней и нижней границ соответственно; позволяет обеспечить связь между параметрами типа. Позволяет создавать экземпляры объекта с типом типа параметра. Исключает создание экземпляра объекта с типом типа параметра (кроме отражения). Параметр типа шаблона класса можно использовать для статических методов и переменных. Параметр типа универсального класса нельзя использовать для статических методов и переменных. Статические переменные, не используемые совместно классами и функциями с параметрами разных типов. Статические переменные, общие для экземпляров классов с параметрами разных типов. Шаблоны классов и функций не обязательно обеспечивают соблюдение отношений типов для параметров типа в их объявлении. Использование неправильного параметра типа приводит к сбою компиляции, часто создавая сообщение об ошибке в коде шаблона, а не в коде пользователя, который его вызывает. Правильное использование шаблонных классов и функций зависит от правильной документации. Метапрограммирование обеспечивает эти возможности ценой дополнительных усилий. Начиная с C++20, концепции для обеспечения этих функций можно использовать . Универсальные классы и функции могут обеспечивать соблюдение отношений типов для параметров типа в их объявлении. Использование неправильного параметра типа приводит к ошибке типа в коде, который его использует. Операции с параметризованными типами в универсальном коде разрешены только способами, безопасность которых может быть гарантирована объявлением. Это приводит к большей безопасности типов за счет гибкости. Шаблоны полны по Тьюрингу (см. Метапрограммирование шаблонов ). Дженерики также полны по Тьюрингу. [ 29 ]
Разнообразный
[ редактировать ]- 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) в пределах заданных ограничений. Таким образом, программа на Java будет иметь единообразное поведение на разных платформах, тогда как программа на C++ может потребовать адаптации для некоторых платформ, но может работать быстрее с более естественными целочисленными размерами для локальной платформы.
Пример сравнения C++ и Java есть в Wikibooks .
Производительность
[ редактировать ]Этот раздел нуждается в дополнительных цитатах для проверки . ( сентябрь 2010 г. ) |
Помимо запуска скомпилированной программы Java, компьютеры, на которых работают приложения Java, обычно также должны запускать виртуальную машину Java (JVM), в то время как скомпилированные программы C++ можно запускать без внешних приложений. Ранние версии Java значительно проигрывали статически компилируемым языкам, таким как C++. Это связано с тем, что программные операторы этих двух тесно связанных языков могут компилироваться в несколько машинных инструкций с помощью C++, а при интерпретации JVM — в несколько байтовых кодов, включающих в себя несколько машинных инструкций. Например:
Оператор Java/C++ | Код, сгенерированный C++ (x86) | Байт-код, сгенерированный Java |
---|---|---|
vector[i]++;
|
mov edx,[ebp+4h]
mov eax,[ebp+1Ch]
inc dword ptr [edx+eax*4]
|
aload_1 iload_2 dup2 iaload iconst_1 iadd iastore |
Поскольку оптимизация производительности — очень сложная проблема, очень сложно количественно оценить разницу в производительности между C++ и Java в общих чертах, а большинство тестов ненадежны и необъективны. Учитывая очень разную природу языков, трудно провести четкие качественные различия. Короче говоря, в Java присущи неэффективность и жесткие ограничения на оптимизацию, учитывая, что она в значительной степени опирается на гибкие абстракции высокого уровня, однако использование мощного JIT-компилятора (как в современных реализациях JVM) может смягчить некоторые проблемы. В любом случае, если неэффективность Java слишком велика, скомпилированный код C или C++ можно вызвать из Java через JNI.
Некоторые недостатки, присущие языку Java, включают в себя, в основном:
- Все объекты размещаются в куче. Несмотря на то, что в современных JVM распределение происходит чрезвычайно быстро, используя «выталкивающее выделение», которое работает аналогично выделению в стеке, на производительность все равно может отрицательно повлиять из-за вызова сборщика мусора. Современные JIT-компиляторы в некоторой степени смягчают эту проблему с помощью escape-анализа или обнаружения escape-последовательности для размещения некоторых объектов в стеке, начиная с Oracle JDK 6.
- Критически важные для производительности проекты, такие как эффективные системы баз данных и библиотеки обмена сообщениями, должны были использовать внутренние неофициальные API, такие как
sun.misc.Unsafe
получить доступ к ручному управлению ресурсами и уметь распределять стек; эффективно манипулировать псевдо-указателями. - Необходимость большого количества приведения типов во время выполнения даже при использовании стандартных контейнеров приводит к снижению производительности. Однако большинство этих приведений статически устраняются JIT-компилятором.
- Гарантии безопасности связаны с затратами во время эксплуатации. Например, компилятор должен включить в код соответствующие проверки диапазона. Защита каждого доступа к массиву с помощью проверки диапазона неэффективна, поэтому большинство JIT-компиляторов будут пытаться устранить их статически или вынести из внутренних циклов (хотя большинство собственных компиляторов для C++ будут делать то же самое, когда проверки диапазона используются опционально).
- Отсутствие доступа к деталям низкого уровня не позволяет разработчику улучшить программу, если компилятор не может это сделать. [ 30 ]
- Обязательное использование ссылочной семантики для всех определяемых пользователем типов в Java может привести к большому количеству избыточных обращений к памяти (или переходов) (если это не исключено JIT-компилятором), что может привести к частым промахам в кэше (так называемому перегрузке кэша ). Кроме того, оптимизация кэша, обычно с помощью структур и алгоритмов данных с поддержкой или без учета кэша , часто может привести к повышению производительности на несколько порядков, а также избежать вырождения временной сложности, которое характерно для многих алгоритмов пессимизации кэша, и поэтому одна из наиболее важных форм оптимизации; ссылочная семантика, предусмотренная в Java, делает такую оптимизацию невозможной на практике (ни программистом, ни JIT-компилятором).
- Сбор мусора , [ 31 ] поскольку эта форма автоматического управления памятью требует дополнительных затрат на память. [ 32 ]
Однако у дизайна Java есть ряд преимуществ, некоторые из которых реализованы, некоторые только теоретически:
- Java Сборка мусора может иметь лучшую согласованность кэша, чем обычное использование malloc / new для распределения памяти. Тем не менее, аргументы существуют [ ласковые слова ] что оба распределителя одинаково фрагментируют кучу, и ни один из них не демонстрирует лучшую локальность кэша. Однако в C++ размещение отдельных объектов в куче происходит редко, и большое количество отдельных объектов обычно выделяется блоками через контейнер STL и/или с помощью распределителя небольших объектов. [ 33 ] [ 34 ]
- Компиляция во время выполнения потенциально может использовать информацию о платформе, на которой выполняется код, для более эффективного улучшения кода. Однако большинство современных компиляторов (C, C++ и т. д.) генерируют несколько путей кода для использования всех вычислительных возможностей данной системы. [ 35 ] Кроме того, можно привести обратный аргумент: нативные компиляторы могут лучше использовать оптимизацию и наборы инструкций для конкретной архитектуры, чем многоплатформенные дистрибутивы JVM.
- Компиляция во время выполнения допускает более агрессивное встраивание виртуальных функций, чем это возможно для статического компилятора, поскольку JIT-компилятор имеет больше информации обо всех возможных целях виртуальных вызовов, даже если они находятся в разных динамически загружаемых модулях. Доступные в настоящее время реализации JVM без проблем встраивают большинство мономорфных, в основном мономорфных и диморфных вызовов, и ведутся исследования по встраиванию также мегаморфных вызовов благодаря недавним динамическим улучшениям вызова, добавленным в Java 7. [ 36 ] Встраивание может обеспечить дальнейшую оптимизацию, такую как векторизация цикла или развертывание цикла , что приводит к огромному увеличению общей производительности.
- В Java синхронизация потоков встроена в язык. [ 19 ] поэтому JIT-компилятор потенциально может с помощью escape-анализа устранить блокировки, [ 37 ] значительно улучшить производительность простого многопоточного кода.
Кроме того, в C++ возникают некоторые проблемы с производительностью:
- Разрешение указателям указывать на любой адрес может затруднить оптимизацию из-за возможности псевдонимов указателей .
- Поскольку код, сгенерированный из различных экземпляров одного и того же шаблона класса в C++, не является общим (как в случае с дженериками со стиранием типов в Java), чрезмерное использование шаблонов может привести к значительному увеличению размера исполняемого кода ( раздуванию кода ). Однако, поскольку шаблоны функций активно встраиваются, они иногда могут уменьшить размер кода, но, что более важно, позволяют компилятору проводить более агрессивный статический анализ и оптимизацию кода, что чаще всего делает их более эффективными, чем код без шаблонов. Напротив, дженерики Java обязательно менее эффективны, чем необобщенный код.
- Поскольку в традиционном компиляторе C++ динамическое связывание выполняется после генерации и оптимизации кода C++, вызовы функций, охватывающие различные динамические модули, не могут быть встроены. Однако современные компиляторы C++, такие как MSVC и Clang+LLVM, предлагают варианты генерации кода во время компоновки, которые позволяют компилировать модули в промежуточные форматы, что позволяет встраивать их на финальном этапе компоновки.
Официальный стандарт и справочник языка
[ редактировать ]Спецификация языка
[ редактировать ]Язык C++ определяется ISO/IEC 14882 , стандартом ISO , опубликованным комитетом ISO/IEC JTC1/SC22/WG21 . последний проект C++17 , выпущенный после стандартизации. Также доступен [ 38 ]
Язык C++ развивается через открытый руководящий комитет, называемый Комитетом по стандартам C++. В состав комитета входят создатель C++ Бьерн Страуструп , организатор Херб Саттер и другие видные деятели, включая многих представителей отраслей и групп пользователей (т. е. заинтересованных сторон). Поскольку комитет является открытым, каждый может свободно присоединяться, участвовать и вносить предложения по предстоящим выпускам стандартов и технических спецификаций. Сейчас комитет стремится выпускать новый стандарт каждые несколько лет, хотя в прошлом строгие процессы проверки и обсуждения приводили к более длительным задержкам между публикацией новых стандартов (1998, 2003 и 2011 годы).
Язык Java определяется Спецификацией языка Java . [ 39 ] книга, изданная Oracle.
Язык Java постоянно развивается посредством процесса, называемого Процессом сообщества Java , а мировое сообщество программистов представлено группой людей и организаций — членов сообщества Java. [ 40 ] — который активно занимается улучшением языка, отправляя публичные запросы — запросы на спецификацию Java — которые должны пройти формальные и публичные проверки, прежде чем они будут интегрированы в язык.
Отсутствие твердого стандарта для Java и несколько более изменчивый характер его спецификаций были постоянным источником критики со стороны заинтересованных сторон, желающих большей стабильности и консерватизма при добавлении новых функций языка и библиотек. Напротив, комитет C++ также постоянно подвергается критике по противоположной причине, т. е. за то, что он слишком строгий и консервативный, а также слишком долго выпускает новые версии.
Товарные знаки
[ редактировать ]«C++» не является товарным знаком какой-либо компании или организации и не принадлежит никому. [ 41 ] «Java» является товарным знаком корпорации Oracle . [ 42 ]
Ссылки
[ редактировать ]Цитаты
[ редактировать ]- ^ Jump up to: а б с Bloch 2018 , стр. xi–xii, предисловие.
- ^ Jump up to: а б Блох 2018 , с. 285, Глава §11, пункт 66. Разумно используйте собственные методы.
- ^ «API беззнаковых целочисленных арифметических операций теперь в JDK 8» . Архивировано из оригинала 25 февраля 2017 года . Проверено 17 марта 2014 г.
- ^ «Учебные пособия по Java: передача информации в метод или конструктор» . Оракул . Проверено 17 февраля 2013 г.
- ^ Jump up to: а б с д и ж г час я Bloch 2018 , стр. 123–125, Глава §2, пункт 7: Удалить устаревшие ссылки.
- ^ «Учебники по Java: объект как суперкласс» . Оракул . Проверено 17 февраля 2013 г. .
- ^ Jump up to: а б с д и ж г час я дж к л Bloch 2018 , стр. 29–33, глава §2, пункт 8. Избегайте финализаторов и очистителей.
- ^ «Программное обеспечение XMPP » Библиотеки» . xmpp.org . Проверено 13 июня 2013 г.
- ^ Jump up to: а б Гетц и др. 2006 , с. 48, §3.4.1 Заключительные поля.
- ^ Роберт К. Мартин (январь 1997 г.). «Java против C++: критическое сравнение» (PDF) . Архивировано из оригинала (PDF) 11 мая 2008 года . Проверено 15 декабря 2007 г.
- ^ «Типы ссылок и значения» . Спецификация языка Java, третье издание . Проверено 9 декабря 2010 г.
- ^ Хорстманн, Кей; Корнелл, Гэри (2008). Ядро Java . Том. Я (Восьмое изд.). Сан Микросистемс. стр. 140–141. ISBN 978-0-13-235476-9 .
Некоторые программисты (и, к сожалению, даже некоторые авторы книг) утверждают, что язык программирования Java использует вызов объектов по ссылке. Однако это неверно. Поскольку это такое распространенное недоразумение, стоит более подробно рассмотреть контрпример... Это обсуждение демонстрирует, что язык программирования Java не использует вызов по ссылке для объектов. Вместо этого ссылки на объекты передаются по значению .
- ^ Дейтел, Пол; Дейтел, Харви (2009). Java для программистов . Прентис Холл. п. 223. ИСБН 978-0-13-700129-3 .
В отличие от некоторых других языков, Java не позволяет программистам выбирать передачу по значению или передачу по ссылке — все аргументы передаются по значению. Вызов метода может передавать в метод два типа значений — копии примитивных значений (например, значения типа int и double) и копии ссылок на объекты (включая ссылки на массивы). Сами объекты не могут быть переданы методам.
- ^ «Семантика вычислений с плавающей запятой в GCC» . Фонд ГНУ . Проверено 20 апреля 2013 г.
- ^ «Компилятор Microsoft C++, /fp (укажите поведение с плавающей запятой)» . Корпорация Майкрософт . Проверено 19 марта 2013 г.
- ^ «Спецификация языка Java 4.3.1: Объекты» . Сан Микросистемс . Проверено 9 декабря 2010 г.
- ^ Bloch 2018 , стр. 87–92, Глава §8, пункт 8: Отдавайте предпочтение композиции, а не наследованию.
- ^ Гетц и др. 2006 , стр. 25–26, §2.3.1 Внутренние блокировки.
- ^ Стандарт языка программирования C++ '11, 5.3.2 Приращение и уменьшение [expr.pre.incr].
- ^ Спецификация языка Java™, Java SE 7 Edition, главы 15.14.2, 15.14.3, 15.15.1, 15.15.2, http://docs.oracle.com/javase/specs/
- ^ Jump up to: а б с Bloch 2018 , стр. 34–36, глава §2, пункт 9. Предпочитайте попытку с ресурсами вместо попытки-наконец.
- ^ Сатиш Чандра Гупта; Раджив Паланки (16 августа 2005 г.). «Утечки памяти Java. Поймай меня, если сможешь» . IBM DeveloperWorks. Архивировано из оригинала 22 июля 2012 года . Проверено 2 апреля 2015 г.
- ^ Как исправить утечки памяти в Java , Велько Крунич (10 марта 2009 г.)
- ^ Создание утечки памяти с помощью на stackoverflow.com Java
- ^ «Введите псевдоним, шаблон псевдонима» . cppreference.com . Проверено 4 октября 2022 г.
- ^ «Переменный шаблон» . cppreference.com . Проверено 4 октября 2022 г.
- ^ Библиотека характеристик типа повышения
- ^ Дженерики Java завершены по Тьюрингу
- ^ Кларк, Натан; Амир Хормати; Сами Йехия; Скотт Мальке (2007). «Liquid SIMD: абстрагирование оборудования SIMD с использованием облегченного динамического отображения». Hpca'07 : 216–227.
- ^ Хундт, Роберт (27 апреля 2011 г.). «Распознавание циклов в C++/Java/Go/Scala» (PDF) . Стэнфорд, Калифорния: Scala Days 2011. Архивировано (PDF) из оригинала 9 октября 2022 года . Проверено 17 ноября 2012 г.
Java демонстрирует большой компонент GC, но хорошую производительность кода. [...] Мы обнаружили, что с точки зрения производительности C++ значительно выигрывает. [...] Версия Java, вероятно, была самой простой в реализации, но труднее всего анализировать производительность. В частности, эффекты, связанные со сбором мусора, были сложны, и их очень трудно настроить; 318 КБ
- ^ Мэтью Герц, Эмери Д. Бергер (2005). «Количественная оценка производительности сборки мусора по сравнению с явным управлением памятью» (PDF) . OOPSLA 2005. Архивировано из оригинала (PDF) 6 июля 2017 года . Проверено 15 марта 2015 г.
В частности, когда сборщик мусора имеет в пять раз больше памяти, чем требуется, его производительность во время выполнения соответствует или немного превышает производительность явного управления памятью. Однако производительность сборки мусора существенно снижается, когда ей приходится использовать кучи меньшего размера. Имея в три раза больше памяти, он работает в среднем на 17% медленнее, а при вдвое большем объеме памяти — на 70% медленнее.
- ^ Александреску, Андрей (2001). Аддисон-Уэсли (ред.). Современный дизайн на C++: применение общих шаблонов программирования и проектирования. Глава 4 . стр. 77–96. ISBN 978-0-201-70431-0 .
- ^ «Библиотека Boost Pool» . Способствовать росту . Проверено 19 апреля 2013 г.
- ^ Использование процессоров с архитектурой IA-32 для проверки производительности во время выполнения
- ^ «Исправление «проблемы» со встраиванием», доктор Клифф Клик | Azul Systems: Блоги» . Архивировано из оригинала 7 сентября 2011 года . Проверено 23 сентября 2011 г.
- ^ Технологическая сеть Oracle для разработчиков Java
- ^ «Рабочий проект стандарта языка программирования C++» (PDF) . Архивировано (PDF) из оригинала 9 октября 2022 года.
- ^ Спецификация языка Java
- ^ Программа Java Community Process (SM) - Участие - Члены JCP
- ^ Часто задаваемые вопросы Бьярна Страуструпа: Владеете ли вы C++?
- ^ ZDNet: Oracle покупает Sun; Сейчас владеет Java. Архивировано 10 апреля 2010 г. на Wayback Machine .
Источники
[ редактировать ]- Блох, Джошуа (2018). «Эффективная Java: Руководство по языку программирования» (третье изд.). Аддисон-Уэсли. ISBN 978-0134685991 .
- Гетц, Брайан; Пайерлс, Тим; Блох, Джошуа; Боубир, Джозеф; Холмс, Дэвид; Леа, Дуг (2006). Параллелизм Java на практике . Эддисон Уэсли. ISBN 0-321-34960-1 .
Внешние ссылки
[ редактировать ]
- Разница между C++ и Java
- Объектно-ориентированное управление памятью: Java против C++
- Глава 2: Чем Java отличается от C , глава из книги «Java в двух словах», Дэвид Фланаган
- Сравнение управления ресурсами Java и C++. Подробный документ с примерами.
- Производительность Java и C... опять же... - Углубленное обсуждение различий в производительности между Java и C/C++.
- Гиперполия — сравнение Java и C++