Java와 C++의 비교
Comparison of Java and C++![]() |
비교 프로그래밍 언어 |
---|
|
Java와 C++는 객체 지향 프로그래밍 언어입니다.많은 언어의 인기 지표에 따르면, 두 언어는 21세기 동안 객체 지향 및 고성능 소프트웨어 개발을 주도해 왔으며, 종종 직접 비교되고 대조됩니다.자바는 약 10년 후에 등장했고 그 구문은 C/C++에 기반을 두고 있다.
설계의 목적
프로그래밍 언어 C++와 Java의 차이는 설계 목표가 다르기 때문에 그 유산으로 추적할 수 있습니다.
C++는 시스템과 애플리케이션 프로그래밍(인프라 프로그래밍)을 위해 설계되었으며, 효율적인 실행을 위해 설계된 절차 프로그래밍 언어 C를 확장했습니다.C++는 객체 지향 프로그래밍, 예외 처리, 평생 기반 자원 관리(RAII), 범용 프로그래밍, 템플릿 메타프로그래밍 및 범용 컨테이너와 알고리즘(Standard Template Library, STL)을 포함한 C++ 표준 라이브러리 지원을 추가했습니다.
Java는 구현 의존성을 최소화하도록 설계된 범용 동시 클래스 기반 객체 지향 프로그래밍 언어입니다.안전하고 휴대성이 뛰어난 Java 가상 머신에 의존합니다.기본 플랫폼의 완전한 추상화를 제공하도록 설계된 광범위한 라이브러리와 함께 번들됩니다.Java는 C++와 유사하지만 호환되지 않는 구문을 사용하는 정적인 유형의 객체 지향 언어입니다.Javadoc이라고 하는 문서 시스템이 포함되어 있습니다.
C++와 Java의 개발 목표는 서로 달랐기 때문에 언어 간에 서로 다른 원칙과 디자인 트레이드오프가 발생하였습니다.차이점은 다음과 같습니다.
C++ | 자바 |
---|---|
C를 객체 지향 프로그래밍 및 일반 프로그래밍으로 확장합니다.C 코드를 가장 적절하게 사용할 수 있습니다. | C++/C 구문의 영향을 강하게 받습니다. |
C 소스 코드와 호환되지만 일부 코너 케이스는 제외됩니다. | C/C++ 코드를 직접 호출하는 방법으로 Java Native Interface 및 최근 Java Native Access를 제공합니다. |
한 번 쓰고 어디든지 컴파일(WOCA). | 한 번 쓰고 어디서나 실행할 수 있습니다(WORA/WORE). |
절차 프로그래밍, 기능 프로그래밍, 객체 지향 프로그래밍, 일반 프로그래밍 및 템플릿 메타프로그래밍을 허용합니다.혼합된 패러다임을 선호합니다. | 절차 프로그래밍, 기능 프로그래밍(Java 8 이후) 및 일반 프로그래밍(Java 5 이후)을 허용하지만 객체 지향 프로그래밍 패러다임을 강력하게 장려합니다.스크립트 언어 작성 지원을 포함합니다. |
대상 명령 집합에 대한 기본 실행 시스템 코드로 실행됩니다. | 가상 시스템에서 실행됩니다. |
개체 유형 및 유형 이름을 제공합니다.Run-Time Type Information(RTTI; 런타임유형정보)을 통한 리플렉션을 허용합니다. | 반사성이 있어 런타임에 메타프로그래밍 및 동적 코드 생성을 가능하게 합니다. |
복수의 바이너리 호환성 규격(일반적으로 Microsoft(MSVC 컴파일러용)과 Itanium/GNU(기타 거의 모든 컴파일러용)를 갖추고 있습니다. | OS 및 컴파일러용 바이너리 호환성 표준이 1개 있습니다. |
옵션 자동 경계 검사(예:at() 에 있어서의 방법.vector 그리고.string 컨테이너) | 모든 조작은 Java의 모든 준거 배포에 의해 바인드 체크되어야 합니다.HotSpot은 경계 검사를 제거할 수 있습니다. |
네이티브 부호 없는 산술 지원. | 네이티브 부호 없는 산술은 지원되지 않습니다.Java 8은 이 중 일부를 변경하지만 양상은 [1]불분명합니다. |
모든 수치 유형에 대해 표준화된 최소 제한이지만 실제 크기는 구현에 정의됩니다.표준 라이브러리에서 표준 유형 사용 가능<cstdint> . | 모든 플랫폼에서 모든 원시 유형의 표준화된 제한 및 크기. |
포인터, 참조 및 pass-by-value는 모든 유형(기본 또는 사용자 정의)에서 지원됩니다. | 모든 유형(기본 유형 및 참조 유형)은 항상 [2]값으로 전달됩니다. |
메모리 관리는, 다음의 방법으로 수동으로 실시할 수 있습니다.new / delete 범위별 또는 스마트 포인터에 의해 자동으로 지정됩니다.개체의 결정론적 파괴를 지원합니다.C++11에서 표준화된 가비지 컬렉션 ABI. 단, 가비지 컬렉션을 구현하기 위해 컴파일러가 필요하지 않습니다. | 가비지 자동 수집비결정론적 finalize() 메서드를 지원합니다.이 메서드의 사용은 [3]권장되지 않습니다. |
리소스 관리는 수동으로 수행하거나 RAI(자동 수명 기반 리소스 관리)를 통해 수행할 수 있습니다. | 리소스 관리는 일반적으로 수동으로 또는 최종자를 통해 자동으로 수행해야 하지만 일반적으로 권장되지 않습니다.자동 범위 기반 리소스 관리를 위한 리소스 시도 기능이 있습니다(버전 7 이후). 내부 API를 사용하여 실행할 수도 있습니다. |
클래스, 구조(Passive Data Structure(PDS; 패시브 데이터 구조) 유형) 및 유니언을 지원하며 힙 또는 스택에 할당할 수 있습니다. | 클래스는 힙에 할당됩니다.Java SE 6은 이스케이프 분석을 통해 최적화하여 일부 개체를 스택에 할당합니다. |
명시적으로 타입을 덮어쓰고 (C와의 호환성을 위해) 암묵적으로 좁혀진 변환을 허용합니다. | 확대한 변환을 제외하고 견고한 타입의 안전성. |
C++ 표준 라이브러리는 제한된 범위와 기능을 가지도록 설계되었지만 언어 지원, 진단, 일반 유틸리티, 문자열, 로케일, 컨테이너, 알고리즘, 반복자, 숫자, 입출력, 난수 생성기, 정규 표현 해석, 스레드 기능, 유형 특성(정적 자기성찰용) 및 표준이 포함됩니다.C 라이브러리부스트 라이브러리는 네트워크 I/O를 포함한 더 많은 기능을 제공합니다. GUI 및 다음과 같은 기타 기능을 위해 풍부한 서드파티 라이브러리가 존재합니다.ACE(Adaptive Communication Environment), Crypto++, 다양한 XMPP 인스턴트 메시징(IM) 라이브러리,[4] OpenLDAP, Qt, gtkmm. | 표준 라이브러리는 릴리즈마다 확대되고 있습니다.버전 1.6까지 라이브러리에는 로케일, 로깅, 컨테이너 및 반복기, 알고리즘, GUI 프로그래밍(시스템 GUI를 사용하지 않음), 그래픽스, 멀티스레딩, 네트워킹, 플랫폼 보안, 인트로스펙션, 동적 클래스 로드, 블로킹 및 논블로킹 I/O 지원이 포함되어 있습니다.XML, XSLT, MIDI, 데이터베이스 연결, 네이밍 서비스(LDAP 등), 암호화, 보안 서비스(Kerberos 등), 인쇄 서비스 및 웹 서비스에 대한 인터페이스 또는 지원 클래스를 제공했습니다.SWT는 플랫폼 고유의 GUI에 대한 추상화를 제공했지만 최신 릴리스에서는 JavaFX로 대체되었습니다.그래픽 액셀러레이션과 CSS 테마가 가능한 UI를 사용할 수 있습니다.단, 어떤 종류의 "네이티브 플랫폼 룩" 지원도 지원하지 않습니다. |
대부분의 연산자에 대한 연산자 오버로드입니다.의미(의미)를 유지하는 것이 좋습니다. | 연산자는 재정의할 수 없습니다.String 클래스의 경우 언어가 + 및 +=를 재정의합니다. |
가상 상속을 포함한 클래스의 단일 및 다중 상속. | 클래스의 단일 상속만 지원합니다. |
컴파일 타임템플릿튜링 완전 메타 프로그래밍을 허용합니다. | 제네릭은 기본적인 타입 파라미터화를 실현하기 위해 사용되지만 컴파일러에 의한 타입 삭제 사용으로 소스 코드에서 바이트 코드로 변환되지 않습니다. |
함수 포인터, 함수 오브젝트, 람다(C++11의 경우) 및 인터페이스. | 함수 참조, 함수 객체 및 람다는 Java 8에 추가되었습니다.클래스(및 클래스인 인터페이스)는 참조로서도 전달할 수 있습니다.SomeClass.class 그리고.someObject.getClass() . |
표준 인라인 문서 메커니즘은 없습니다.서드파티 소프트웨어(Doxygen 등)가 존재합니다. | 모든 시스템 클래스 및 메서드에 대한 광범위한 Javadoc 문서 표준. |
const 오브젝트를 변경하지 않는 불변 변수 및 멤버 함수를 정의하기 위한 키워드입니다.const-ness는 컴파일 시에 오브젝트의 가변성에 관해 코드의 정확성을 강제하기 위한 수단으로서 전파됩니다(const-correctness 참조). | final 의 버전을 나타냅니다.const (등가)type* const 오브젝트 포인터 및const 원시 유형용입니다.읽기 전용 인터페이스 및 개체 캡슐화를 통해 달성되는 개체 멤버의 불변성. |
지원 대상goto 진술. | 루프 및 스테이트먼트블록이 있는 라벨을 지원합니다. goto 는 예약된 키워드이지만 Java 사양에서는 "unused"로 표시되어 있습니다. |
소스 코드는 크로스 플랫폼(Windows, BSD, Linux, macOS, Solaris 등의 경우 수정 없이 컴파일 가능)으로 작성하여 플랫폼 고유의 기능을 사용하도록 작성할 수 있습니다.일반적으로 네이티브 기계 코드로 컴파일되며 각 타깃 플랫폼에 대해 재컴파일해야 합니다. | JVM의 Java 바이트 코드로 컴파일됩니다.바이트 코드는 Java 플랫폼에 의존하지만 일반적으로 운영 체제 고유의 기능과는 독립적입니다. |
언어 기능
구문
- Java 구문에는 단순한 LALR 파서로 해석할 수 있는 컨텍스트프리 문법이 있습니다.C++ 의 해석은 보다 복잡합니다.예를들면,
Foo<1>(3);
는 Foo가 변수인 경우 비교 시퀀스이지만 Foo가 클래스 템플릿의 이름인 경우 개체를 만듭니다. - C++에서는 네임스페이스 수준의 상수, 변수 및 함수를 사용할 수 있습니다.Java에서는 이러한 엔티티는 특정 유형에 속해야 하므로 유형 정의(클래스 또는 인터페이스) 내에서 정의되어야 합니다.
- C++에서는 객체는 값이지만 Java에서는 그렇지 않습니다.C++는 기본적으로 값 의미론을 사용하는 반면 Java는 항상 참조 의미론을 사용합니다.C++에서 참조 의미론을 선택하기 위해 포인터 또는 참조를 사용할 수 있습니다.
C++ | 자바 |
---|---|
학급 푸우 { // 클래스 Foo를 선언합니다. 인트 x = 0; // Private Member 변수.그것은 그럴거다. // 0으로 초기화됩니다. // 생성자가 설정하지 않습니다. // (C++11부터) 일반의: 푸우() : x(0) // Foo 생성자, 초기화 {} // x ~0 。이니셜라이저가 // 생략. 변수는 다음과 같습니다. // 다음과 같은 값으로 초기화됩니다. // x 선언 시 지정되었습니다. 인트 막대기(인트 i) { // 멤버 함수 bar() 돌아가다 3*i + x; } }; | 학급 푸우 { // 클래스 Foo를 정의합니다. 사적인 인트 x; // 멤버 변수, 일반적으로 선언됨 // 캡슐화를 적용하기 위해 비공개로 지정 // 기본 0으로 초기화됨 일반의 푸우() { // Foo 생성자 } // 디폴트로 제공되는 no-internal 생성자 일반의 인트 막대기(인트 i) { // 멤버 메서드 bar() 돌아가다 3*i + x; } } |
푸우 a; // 가 Foo 오브젝트 값임을 선언합니다. // 기본 생성자를 사용하여 초기화되었습니다. // 다른 생성자를 다음과 같이 사용할 수 있습니다. 푸우 a(args); // 또는 (C++11): 푸우 a{args}; | 푸우 a = 신규 푸우(); // 가 새로운 Foo 객체에 대한 참조임을 선언합니다. // 기본 생성자를 사용하여 초기화됨 // 다른 생성자를 다음과 같이 사용할 수 있습니다. 푸우 a = 신규 푸우(args); |
푸우 b = a; // a의 내용을 새로운 Foo 객체 b에 복사합니다. // 대체 구문은 "Foo b(a)"입니다. | // Foo b = a; // b가 a가 가리키는 오브젝트에 대한 참조임을 선언합니다. 푸우 b = a.클론(); // 가 가리키는 개체의 내용을 복사합니다. // 새 Foo 개체로 이동; // 이 새 개체를 가리키도록 기준 b를 설정합니다. // Foo 클래스는 복제 가능 인터페이스를 구현해야 합니다. // 이 코드를 컴파일하려면 |
a.x = 5; // 오브젝트 a를 변경합니다. | a.x = 5; // 가 참조하는 오브젝트를 변경합니다. |
표준::외치다 << > b.x << > 표준::끝; // 출력 0, b는 // 다른 오브젝트 | 시스템..나가..인쇄(b.x); // 출력 0, b는 다음을 가리키기 // 다른 오브젝트 |
푸우 *c; // c가 에 대한 포인터임을 선언합니다. // Foo 객체(처음에는) // 정의되지 않음, 어디든 가리킬 수 있음) | 푸우 c; // c가 Foo에 대한 참조임을 선언합니다. // 오브젝트(c가 클래스 멤버인 경우 null이 됩니다). // 사용하기 전에 c를 초기화해야 합니다. // 로컬 변수인 경우) |
c = 신규 푸우; // c는 연산자 new가 작성한 Foo 객체의 주소 값으로 설정됩니다. | c = 신규 푸우(); // 새 Foo 개체를 참조하기 위해 c를 바인딩합니다. |
푸우 &d = *c; // c가 가리키는 동일한 개체를 참조하기 위해 d를 바인딩합니다. | 푸우 d = c; // d를 바인드하여 c와 같은 오브젝트를 참조합니다. |
c->x = 5; // c가 가리키는 오브젝트를 변경합니다. | c.x = 5; // c에서 참조하는 오브젝트를 변경합니다. |
d.막대기(5); // 에 대해서 Foo::bar() 를 호출합니다. c->막대기(5); // *c에 대해 Foo::bar()를 호출합니다. | d.막대기(5); // 에 대해 Foo.bar() 를 호출합니다. c.막대기(5); // c에 대해 Foo.bar()을 호출합니다. |
표준::외치다 << > d.x << > 표준::끝; // 출력 5는 d가 참조하기 때문에 // c가 가리키는 동일한 객체 | 시스템..나가..인쇄(d.x); // 출력 5는 d가 참조하기 때문에 // c와 같은 오브젝트 |
- C++에서는 클라이언트코드가 const 오브젝트를 수정하지 않도록 포인터 또는 const 오브젝트에 대한 참조를 선언할 수 있습니다.또한 함수 및 메서드는 "const" 키워드를 사용하여 포인터가 가리키는 개체를 수정하지 않음을 보장할 수 있습니다.이것에 의해, const-correction이 강제됩니다.
- 자바에서, 대부분의 경우, const-correctness는 클래스의 인터페이스의 의미론에 의존해야 한다. 즉, 라벨이 붙은 공개 데이터 멤버를 제외하고, 그것은 강하게 강제되지 않는다.
final
.
C++ | 자바 |
---|---|
컨스턴트 푸우 *a; // 개체를 수정할 수 없습니다. // 가 가리키는 ~ | 최종 푸우 a; // "최종" 참조 선언: // 개체를 수정할 수 있습니다. // 단, 참조는 항상 다음을 가리킵니다. // 할당된 첫 번째 개체로 이동합니다. |
a = 신규 푸우(); | a = 신규 푸우(); // 생성자에만 있음 |
a->x = 5; // 부정한 | a.x = 5; // LAGAL. 객체의 멤버는 아직 수정할 수 있습니다. // 선언 클래스에서 명시적으로 final로 선언되지 않는 한 |
푸우 *컨스턴트 b = 신규 푸우(); // "const" 포인터의 선언 // 개체를 수정할 수 있습니다. // 단, 포인터는 항상 포인터를 가리킵니다. // 여기에 할당된 개체로 이동합니다. | 최종 푸우 b = 신규 푸우(); // "최종" 참조 선언 |
b = 신규 푸우(); // ILOGAL. 다시 바인딩할 수 없습니다. | b = 신규 푸우(); // ILOGAL. 다시 바인딩할 수 없습니다. |
b->x = 5; // LAGAL, 오브젝트는 아직 수정할 수 있습니다. | b.x = 5; // LAGAL, 오브젝트는 아직 수정할 수 있습니다. |
- C++ 지원
goto
스파게티 코드 프로그래밍으로 이어질 수 있습니다.goto 스테이트먼트(실제 코드에서는 거의 볼 수 없고 매우 권장되지 않음)를 제외하고 Java와 C++는 기본적으로 동일한 제어 흐름 구조를 가지고 있으며 구조화된 제어 플로우를 적용하도록 설계되어 있으며 break and continue 스테이트먼트에 의존하여 다음과 같은 기능을 제공합니다.goto
- like 함수.일부 코멘트는 이러한 라벨이 붙은 흐름제어문이 구조화 [5]프로그래밍의 단일 출구점 속성을 파괴한다고 지적합니다. - C++는 Java에 대부분 없는 낮은 수준의 기능을 제공합니다(한 가지 주목할 만한 예외는
sun.misc.Unsafe
직접 메모리 액세스 및 조작을 위한 API).C++에서는 포인터를 사용하여 특정 메모리 위치를 조작할 수 있습니다.이것은, 저레벨의 operating system 컴퍼넌트를 기술하기 위해서 필요한 태스크입니다.마찬가지로 많은 C++ 컴파일러가 인라인어셈블러를 지원하고 있습니다.어셈블리 언어 코드는 C 프로그램으로 Import할 수 있으며 그 반대도 가능합니다.이것은 C 언어를 더욱 빠르게 만든다.Java에서는 이러한 코드가 외부 라이브러리에 존재해야 하며 Java Native Interface를 통해서만 액세스할 수 있으며 각 콜에 상당한 오버헤드가 발생합니다.
의미론
- C++ 에서는, 함수/메서드의 인수에 디폴트치를 사용할 수 있습니다.Java는 그렇지 않습니다.다만, 메서드 오버로드를 사용하면, Java 로 같은 결과를 얻을 수 있습니다만, 용장 스탭 코드를 생성할 수 있습니다.
- 자바가 클래스이기 때문에 C++ 컴파일에 필요한 최소한의 코드는 함수입니다.
- C++ 에서는 네이티브타입간의 암묵적인 변환(일부 좁혀진 변환 포함)이 가능해져, 유저 정의 타입을 포함한 암묵적인 변환도 정의할 수 있습니다.Java에서는 네이티브 유형 간의 확장 변환만 암시되며, 다른 변환에서는 명시적인 캐스트 구문이 필요합니다.
- 그 결과, 루프 상태가 됩니다(
if
,while
의 종료 조건for
Java 및 C++ 에서는 둘 다 다음과 같은 부울식을 필요로 합니다.if(a = 5)
int에서 부울로의 암묵적인 압축 변환은 없지만 C++로 컴파일되기 때문에 Java에서 컴파일 오류가 발생합니다.이것은 만약 코드가 오타가 났을 때 편리합니다.if(a == 5)
의도된 것입니다.다만, 현재의 C++ 컴파일러에서는, 통상, 이러한 할당이 조건식내에서 실행되면 경고가 발생합니다.마찬가지로 독립형 비교문(예:a==5;
부작용 없이 보통 경고로 이어집니다.
- 그 결과, 루프 상태가 됩니다(
- 함수에 파라미터를 전달하기 위해 C++는 pass-by-reference와 pass-by-value를 모두 지원합니다.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의 strict fp), 준IEEE 및 엄밀한IEEE라고 하는 라벨을 붙이면, 대부분의 C++ 실장에서는 디폴트에서는 고속 또는 엄밀한IEEEE로 전환하는 옵션이 디폴트에서는 고속으로, Java에서는 일관되게 전환하는 옵션이 디폴트로 되어 있다고 말할 수 있습니다.
- C++ 에서는, 포인터는 메모리 주소의 값으로 직접 조작할 수 있습니다.Java 참조는 [11]객체에 대한 포인터입니다.Java 참조에서는 메모리 주소에 직접 액세스하거나 포인터 산술로 메모리 주소를 조작할 수 없습니다.C++에서는 포인터에 대한 포인터, int와 double에 대한 포인터, 임의의 메모리 위치에 대한 포인터를 구성할 수 있습니다.Java 참조는 오브젝트에만 액세스하며 프리미티브, 기타 참조 또는 임의 메모리 위치에는 액세스하지 않습니다.Java에서는 메모리 읽기 및 쓰기가 임의의 값으로 가능합니다.
sun.misc.Unsafe
단, API는 권장되지 않으며 권장되지 않습니다. - C++에서 포인터는 함수 또는 멤버 함수(함수 포인터)를 가리킬 수 있습니다.Java의 동등한 메커니즘은 객체 또는 인터페이스 참조를 사용합니다.
- C++는 스택에 할당된 객체를 통해 메모리 및 기타 결정론적 객체 파괴를 지원하는 시스템 리소스를 자동으로 관리하기 위해 사용되는 기술인 범위 지정 리소스 관리를 지원합니다.C++의 범위 내 자원 관리는 보증할 수 없지만 (적절한 디스트럭터가 있는 오브젝트도 다음 방법으로 할당 가능)
new
삭제되지 않은 채로)를 사용하면 효과적인 자원 관리 수단을 얻을 수 있습니다.공유 리소스는 다음 방법으로 관리할 수 있습니다.shared_ptr
, 와 함께weak_ptr
주기 참조를 끊습니다.Java는 가비지 컬렉션을 사용한 자동 메모리 관리를 지원하므로 주기적인 참조가 존재하는 경우에도 도달할 수 없는 오브젝트를 해방할 수 있지만 가비지 컬렉션이 마지막 오브젝트 직후에 발생한다고 보증되지 않기 때문에 다른 시스템 리소스(파일, 스트림, 창, 통신 포트, 스레드 등)를 명시적으로 해방해야 합니다.참조는 포기됩니다. - C++에는 사용자 정의 연산자 오버로드 기능이 있습니다.연산자 오버로드를 통해 사용자 정의 유형은 이러한 연산자에 대한 사용자 정의 구현을 통해 원시 유형처럼 연산자(산술, 비교 등)를 지원할 수 있습니다.일반적으로 연산자의 의미를 유지하는 것이 좋습니다.Java는 연산자 오버로드를 지원하지 않습니다(단, 라이브러리는 문자열 연결에 추가 연산자를 사용합니다).
- Java는 표준 API(Application Programming Interface) 지원을 통해 임의의 새 코드를 리플렉션 및 동적 로딩할 수 있습니다.
- C++는 바이너리의 정적 및 동적 링크를 지원합니다.
- 자바에는 제네릭이 있으며, 그 주된 목적은 타입 세이프 컨테이너를 제공하는 것입니다.C++에는 범용 프로그래밍 및 메타프로그래밍을 보다 광범위하게 지원하는 컴파일 타임 템플릿이 있습니다.Java에는 주석 처리 도구를 통해 클래스와 메타프로그래밍에 임의의 커스텀 메타데이터를 추가할 수 있는 주석이 있습니다.
- Java와 C++는 모두 네이티브타입(기본형 또는 임베디드형이라고도 함)과 사용자 정의타입(복합형이라고도 함)을 구별합니다.Java의 경우 네이티브타입은 값 의미론만을 가지며 복합타입은 참조 의미론만을 가집니다.C++에서는 모든 타입이 값 의미론을 가지고 있지만, 임의의 타입에 대한 참조를 생성할 수 있으며, 참조 의미론을 통해 객체를 조작할 수 있습니다.
- C++는 임의의 클래스의 다중 상속을 지원합니다.Java에서는 클래스가 하나의 클래스에서만 파생될 수 있지만 클래스는 여러 인터페이스를 구현할 수 있습니다(즉, 여러 유형의 상속을 지원하지만 구현의 단일 상속만 지원).
- Java는 인터페이스와 클래스를 명시적으로 구분합니다.C++ 에서는, 복수의 상속과 순수 가상 함수에 의해서, Java 인터페이스와 거의 같은 기능을 하는 클래스를 정의할 수 있습니다.단, 약간의 차이는 있습니다.
- Java는 멀티스레딩을 위한 언어 및 표준 라이브러리를 모두 지원합니다.그
synchronized
Java 키워드는 멀티스레드 어플리케이션을 지원하기 위해 단순하고 안전한 뮤텍스 잠금을 제공합니다.Java는 또한 보다 고급 멀티스레딩 동기화를 위한 강력하고 복잡한 라이브러리를 제공합니다.C++11의 경우에만 C++에서의 멀티스레딩과 스레드 작성 및 다수의 동기화 프리미티브에 대한 라이브러리 지원을 위한 정의된 메모리 모델이 있습니다.이를 위한 서드파티 라이브러리도 많이 있습니다. - C++ 멤버 함수는 가상 함수로 선언할 수 있습니다.즉, 호출되는 메서드는 객체의 런타임 유형(일명 동적 디스패치)에 따라 결정됩니다.디폴트에서는, C++ 의 메서드는 가상이 아닙니다(즉, opt-in virtual).Java 에서는 기본적으로는 가상 메서드가 사용되지만 를 사용하여 비가상 메서드를 만들 수 있습니다.
final
키워드(즉, opt-out virtual). - C++ 열거형은 원시 유형으로 정수 유형으로의 암묵적 변환을 지원합니다(단, 정수 유형으로부터의 변환은 지원하지 않습니다).Java 열거는 다음과 같습니다.
public static enum{enumName1,enumName2}
수업처럼 사용됩니다.또 다른 방법은 다른 클래스를 만드는 것입니다.java.lang.Enum<E>
따라서 컨스트럭터, 필드 및 메서드를 다른 클래스와 동일하게 정의할 수 있습니다.C++11의 경우, C++는 더 많은 유형 안전성과 스토리지 유형의 명시적 사양을 제공하는 강력한 유형의 열거형도 지원합니다. - 단항 연산자 '++' 및 '--': C++에서 "피연산자는 수정 가능한 l 값이어야 합니다.[아쉬움]결과는 업데이트된 오퍼랜드입니다.lvalue..."[12] 그러나 Java에서는 "위의 이진수치 프로모션에 언박싱 변환과 값 집합 변환이 포함될 수 있습니다.필요에 따라 변수에 [13]저장되기 전의 합계에 값 집합 변환 {and/또는 [... boxing conversion}을 적용합니다. 즉, Java에서는 초기화 "Integer i=2;" 후에 "+i;"가 새로운 객체를 할당하여 참조 i를 변경하지만 C++에서는 객체가 그대로입니다.
자원 관리
- Java는 실시간 Java 사양을 통해 특정 상황에서 바이패스될 수 있는 자동 가비지 수집을 제공합니다.C++에서의 메모리 관리는 보통 컨스트럭터, 디스트럭터 및 스마트 포인터를 통해 이루어집니다.C++ 표준에서는 가비지 수집을 허용하지만 가비지 수집은 필요하지 않습니다.가비지 컬렉션은 실제로 거의 사용되지 않습니다.
- C++ 는, 임의의 메모리 블록을 할당할 수 있습니다.Java는 객체 인스턴스화를 통해서만 메모리를 할당합니다.임의의 메모리 블록은 Java에서 바이트 배열로 할당할 수 있습니다.
- Java와 C++는 자원 관리에 다른 관용구를 사용합니다.Java는 주로 메모리를 회수할 수 있는 가비지 컬렉션에 의존하고 C++는 주로 RAI(Resource Acquisition Is Initialization) 관용어에 의존합니다.이는 두 언어 간의 몇 가지 차이에서 나타납니다.
- C++에서는 컴파운드 타입의 오브젝트를 로컬스택바인드 변수로 할당하는 것이 일반적입니다.이 변수는 범위를 벗어나면 파기됩니다.Java 복합에서는 유형이 항상 힙에 할당되고 가비지 컬렉터에 의해 수집됩니다(이스케이프 분석을 사용하여 힙 할당을 스택 할당으로 변환하는 가상 시스템은 제외).
- C++에는 소멸자가 있고 Java에는 최종자가 있습니다.둘 다 객체의 할당 해제 전에 호출되지만 크게 다릅니다.C++ 객체의 소멸자는 암시적으로 호출하거나(스택 바인딩 변수의 경우), 명시적으로 호출하여 객체의 할당을 해제해야 합니다.디스트럭터는 오브젝트가 할당 해제된 프로그램의 포인트 직전에 동기적으로 실행됩니다.따라서 C++에서의 동기적이고 조정된 초기화 해제 및 할당 해제는 RAII 관용구를 충족시킵니다.Java에서는 객체 할당 해제가 가비지 컬렉터에 의해 암묵적으로 처리됩니다.Java 개체의 최종자는 마지막으로 액세스한 후 할당 해제되기 전에 비동기적으로 호출됩니다.최종자가 필요한 개체는 거의 없습니다.최종자는 할당을 해제하기 전에 개체 상태의 정리를 보장해야 하는 개체에만 필요하며, 일반적으로 JVM 외부의 리소스를 해방합니다.또한 최종자는 성능 저하가 심하고 오브젝트 할당 해제에 걸리는 시간이 크게 증가하므로 Java 9에서는 사용이 권장되지 않습니다.
- C++의 RAII에서는 일반적으로 한 가지 유형의 리소스가 소규모 클래스 내에 래핑됩니다.이 클래스는 구축 시 리소스를 할당하고 파괴 시 리소스를 해방하며 이들 포인트 사이에 리소스에 대한 액세스를 제공합니다.RAII 오브젝트의 디스트럭터는 이 클래스의 오브젝트로 자동 호출되므로 이러한 RAII 오브젝트만을 포함하는 클래스는 디스트럭터를 정의할 필요가 없습니다.Java에서는 try/catch/finally 구성을 사용하여 자원의 안전한 동기적 할당 해제를 결정적으로 수행할 수 있습니다.
- C++에서는 이미 할당 해제된 객체에 대한 오래된 참조인 덩글링 포인터를 가질 수 있습니다.일반적으로 매달림 포인터를 사용하려고 하면 프로그램 오류가 발생합니다.Java에서는 가비지 컬렉터가 참조된 개체를 삭제하지 않습니다.
- C++에서는 초기화되지 않은 원시 개체를 가질 수 있습니다.Java는 기본 초기화를 적용합니다.
- C++에서는 유효한 참조가 없는 오브젝트를 할당할 수 있습니다.이러한 도달 불가능한 오브젝트는 파기(할당 해제)할 수 없으며 메모리 누수가 발생합니다.반대로 Java에서는 (사용자 프로그램에 의해) 도달할 수 없을 때까지 가비지 컬렉터에 의해 오브젝트가 할당 해제되지 않습니다.(Java 가비지 컬렉터와 연계하여 다양한 강도의 도달 가능성을 허용하는 약한 참조가 지원됩니다).Java에서의 가비지 수집은 많은 메모리 누수를 방지하지만 상황에 [14][15][16]따라서는 누수가 발생할 수 있습니다.
라이브러리
- C++는 플랫폼 고유의 라이브러리에서 일반적으로 이용 가능한 많은 기능에 대한 크로스 플랫폼 액세스를 제공합니다.Java에서 네이티브 운영 체제 및 하드웨어 기능에 직접 액세스하려면 Java 네이티브 인터페이스를 사용해야 합니다.
런타임
C++ | 자바 |
---|---|
C++는 기계코드에 직접 컴파일 되고, 기계코드는 중앙처리장치에 의해 직접 실행된다. | Java는 실행 시 Java Virtual Machine(JVM; Java 가상 머신)이 해석하는 바이트 코드로 컴파일됩니다.실제 Java 구현에서는 네이티브 머신 코드로 적시 컴파일을 수행합니다.또는 GNU 컴파일러 for Java는 머신 코드로 직접 컴파일 할 수 있습니다. |
- 그 제약이 없는 표현성으로 인해 낮은 수준의 C++ 언어 기능(예: 선택되지 않은 배열 액세스, 원시 포인터, 유형 펀닝)은 컴파일 시 또는 런타임에 오버헤드가 없으면 확실하게 체크할 수 없습니다.관련된 프로그래밍 오류로 인해 낮은 수준의 버퍼 오버플로 및 분할 오류가 발생할 수 있습니다.표준 템플릿 라이브러리는 이러한 오류를 방지하기 위해 고급 RAII 추상화(벡터, 목록, 지도 등)를 제공합니다.Java에서는 낮은 수준의 오류가 발생할 수 없거나 Java Virtual Machine(JVM; Java 가상 머신)에 의해 검출되어 예외 형식으로 애플리케이션에 보고됩니다.
- Java 언어에서는 Out-of-Bounds 어레이 액세스의 경우 특정 동작이 필요하며, 일반적으로 어레이 액세스의 경계를 확인해야 합니다.이로 인해 발생할 수 있는 불안정 요인이 제거되지만 일반적으로 실행 속도가 느려집니다.경우에 따라서는, 특히 Java 7 이후, 컴파일러 분석에 의해서, 경계 체크가 불필요하다는 것을 증명해, 그것을 없앨 수 있습니다.C++에는 네이티브 어레이의 Out-Bounds 액세스에 필요한 동작이 없기 때문에 네이티브 어레이에 대한 경계 검사가 필요하지 않습니다.그러나 std::vector와 같은 C++ 표준 라이브러리 컬렉션은 옵션인 경계 검사를 제공합니다.요약하면 Java 어레이는 "보통 안전, 약간 제약, 오버헤드 발생"인 반면 C++ 네이티브 어레이는 "옵션의 오버헤드가 있고, 약간 제약이 없으며, 안전하지 않을 수 있습니다."
템플릿 vs.
C++와 Java는 각각 범용 프로그래밍, 템플릿 및 범용 기능을 제공합니다.비슷한 문제를 해결하기 위해 만들어졌고 구문도 비슷하지만, 그것들은 상당히 다르다.
C++ 템플릿 자바 제네릭스 클래스, 함수, 별칭[17] 및 변수를[18] 템플릿화할 수 있습니다. 클래스 및 메서드를 일반화할 수 있습니다. 파라미터는 임의의 유형, 적분값, 문자 리터럴 또는 클래스 템플릿에서 바리에타일 수 있습니다. 매개 변수는 상자에 들어 있는 원시 유형(예: 정수, 부울...)을 포함한 모든 참조 유형이 될 수 있습니다. 컴파일 시 각 파라미터 세트에 대해 클래스 또는 함수의 개별 인스턴스화가 생성됩니다.클래스 템플릿의 경우 사용되는 멤버 함수만 인스턴스화됩니다. 클래스 또는 함수의 한 버전이 컴파일되어 모든 유형 파라미터에 대해 작동합니다(타입 삭제를 통해). 서로 다른 매개 변수로 인스턴스화된 클래스 템플릿 객체는 런타임에 서로 다른 유형을 가집니다(즉, 개별 템플릿 인스턴스화는 서로 다른 클래스입니다). 유형 매개 변수는 컴파일되면 지워집니다. 유형 매개 변수가 서로 다른 클래스의 개체는 런타임에 동일한 유형이 됩니다.이로 인해 다른 생성자가 발생합니다.이 유형 삭제로 인해 일반 클래스의 다른 인스턴스를 사용하여 메서드를 오버로드할 수 없습니다. 클래스 또는 함수 템플릿을 사용하려면 변환 유닛 내에서 구현이 표시되어야 합니다.이는 보통 헤더 파일에 정의가 있거나 헤더 파일에 포함되어 있음을 의미합니다.C++11에서는 외부 템플릿을 사용하여 일부 인스턴스의 컴파일을 분리할 수 있습니다. 컴파일된 클래스 파일에서 클래스 또는 함수의 시그니처를 사용하면 됩니다. 템플릿은 특수화할 수 있습니다.특정 템플릿파라미터에 대해 별도의 구현을 제공할 수 있습니다. 제네릭스는 특수화할 수 없습니다. 템플릿 파라미터에는 기본 인수를 지정할 수 있습니다.C++11 이전 버전에서는 템플릿클래스에 대해서만 허용되고 함수는 허용되지 않았습니다. 일반 형식 매개 변수에는 기본 인수를 사용할 수 없습니다. 와일드카드는 지원되지 않습니다.대신 반환 유형은 종종 중첩된 typedef로 사용할 수 있습니다(또한 C++11 키워드가 추가되었습니다). auto
컴파일 시에 판별할 수 있는 임의의 타입의 와일드카드로서 기능합니다).유형 매개 변수로 지원되는 와일드 카드. 유형 매개 변수의 경계를 직접 지원하지 않지만 메타프로그래밍이 이를 제공합니다[19]. 상한 및 하한에 대해 각각 "확장" 및 "슈퍼"를 사용하여 유형 매개 변수의 경계를 지원합니다. 유형 매개 변수 간의 관계를 적용할 수 있습니다. 매개 변수 유형으로 개체를 인스턴스화할 수 있습니다. 매개 변수 유형의 유형을 사용하여 개체를 인스턴스화할 수 없습니다(반사를 통한 개체 제외). 클래스 템플릿의 유형 매개 변수는 정적 메서드 및 변수에 사용할 수 있습니다. 정적 메서드 및 변수에 일반 클래스의 형식 매개 변수를 사용할 수 없습니다. 유형 매개 변수가 다른 클래스 및 함수 간에 공유되지 않는 정적 변수입니다. 유형 매개 변수가 다른 클래스의 인스턴스 간에 공유되는 정적 변수입니다. 클래스 및 함수 템플릿은 선언에서 유형 매개 변수에 대해 유형 관계를 적용하지 않습니다.잘못된 유형 매개 변수를 사용하면 컴파일 실패가 발생하고 종종 템플릿 코드를 호출하는 사용자 코드가 아닌 템플릿 코드 내에서 오류 메시지가 생성됩니다.템플리트 클래스 및 함수의 적절한 사용은 적절한 설명서에 따라 달라집니다.메타프로그래밍은 이러한 기능을 제공하기 위해 노력을 더합니다.C++11에서 이 문제를 해결하기 위한 제안이 있었습니다. 이른바 개념으로, 다음 표준을 위해 계획되어 있습니다. 일반 클래스 및 함수는 선언의 유형 매개 변수에 대해 유형 관계를 적용할 수 있습니다.잘못된 유형 매개 변수를 사용하면 해당 매개 변수를 사용하는 코드 내에서 유형 오류가 발생합니다.일반 코드의 매개 변수 유형에 대한 작업은 선언에 의해 안전성을 보장할 수 있는 방식으로만 허용됩니다.그 결과 유연성이 희생되어 더 큰 유형의 안전성이 실현됩니다. 템플릿은 튜링 완료입니다(템플릿 메타프로그래밍 참조). 제네릭도 튜링 완전[20]
여러가지 종류의
- Java와 C++는 다른 수단을 사용하여 코드를 여러 소스 파일로 나눕니다.Java는 모든 프로그램 정의에 대해 파일 이름과 경로를 지정하는 패키지 시스템을 사용합니다.컴파일러는 실행 가능한 클래스 파일을 가져옵니다.C++는 헤더 파일 소스 코드 포함 시스템을 사용하여 소스 파일 간에 선언을 공유합니다.
- 컴파일된 Java 코드 파일은 일반적으로 C++의 코드 파일보다 작습니다.Java 바이트코드는 보통 네이티브 머신 코드보다 콤팩트하고 Java 프로그램은 정적으로 링크되지 않습니다.
- C++ 컴파일은 텍스트 전처리 단계를 추가하지만 Java는 그렇지 않습니다.따라서 일부 사용자는 조건부 컴파일을 보다 효과적으로 지원하기 위해 빌드 프로세스에 사전 처리 단계를 추가합니다.
- Java의 나눗셈 연산자와 계수 연산자는 0으로 잘라내도록 잘 정의되어 있습니다.C++(pre-C++11)에서는 이들 연산자가 0으로 잘라낼지, 아니면 "-infinity로 잘라낼지 지정하지 않습니다. Java 및 C++11에서는 -3/2가 항상 -1이 되지만 플랫폼에 따라 C++03 컴파일러는 -1 또는 -2를 반환할 수 있습니다.C99는 Java 및 C++11과 같은 방법으로 분할을 정의합니다.두 언어 모두 (a와 b는 정수형)를 보증합니다.
(a/b)*b + (a%b) == a
(b!= 0)의 모든 a 및 b ! = 0C++03 버전은 프로세서에 네이티브인 잘라내기 모드를 선택할 수 있기 때문에 더 빠를 수 있습니다. - 정수 타입의 사이즈는 Java(int는 32비트, long은 64비트)로 정의됩니다.C++에서는 정수 및 포인터의 사이즈는 컴파일러와 어플리케이션바이너리 인터페이스(ABI)에 의존합니다.따라서 Java 프로그램은 플랫폼 전체에서 일관된 동작을 하는 반면 C++ 프로그램은 일부 플랫폼에서는 적응이 필요할 수 있지만 로컬플랫폼에서는 보다 자연스러운 정수 크기를 사용하여 더 빠르게 실행될 수 있습니다.
C++와 Java를 비교하는 예는 Wikibooks에 있습니다.
성능
이 섹션은 확인을 위해 추가 인용문이 필요합니다.(2010년 9월 (이 의 을 확인) |
컴파일된 Java 프로그램을 실행하는 것 외에 Java 애플리케이션을 실행하는 컴퓨터에서는 일반적으로 Java Virtual Machine(JVM; Java 가상 머신)도 실행해야 하며 컴파일된 C++ 프로그램은 외부 애플리케이션 없이 실행할 수 있습니다.Java의 초기 버전은 C++와 같은 정적 컴파일 언어보다 훨씬 더 뛰어났습니다.이는 밀접하게 관련된 이 두 언어의 프로그램 문이 C++를 사용하여 몇 개의 기계 명령어로 컴파일되는 반면 JVM에 의해 해석될 때 각각 여러 개의 기계 명령이 포함된 여러 바이트 코드로 컴파일되는 경우가 있기 때문입니다.예를 들어 다음과 같습니다.
Java/C++문 | C++ 생성 코드(x86) | Java 생성 바이트 코드 |
---|---|---|
vector[i]++; | 움직이다 엣지,[에브피+4시간] 움직이다 이액스,[에브피+1채널] 주식회사 워드 ptr [엣지+이액스*4] | aload_1 iload_2 dup2 iaload iconst_1 istore 추가 |
퍼포먼스 최적화는 매우 복잡한 문제이기 때문에 C++와 Java의 퍼포먼스 차이를 일반적으로 정량화하는 것은 매우 어렵습니다.또한 대부분의 벤치마크에서는 신뢰성이 떨어지고 편중되어 있습니다.언어의 성질이 매우 다르기 때문에 명확한 질적 차이도 도출하기 어렵다.한마디로 Java는 유연하고 높은 수준의 추상화에 크게 의존하고 있기 때문에 Java 최적화에 내재된 비효율성과 한계가 있지만 강력한 JIT 컴파일러(현대 JVM 구현에서와 같은)를 사용하면 일부 문제를 완화할 수 있습니다.어느 경우든 Java의 비효율성이 너무 클 경우 컴파일된 C 또는 C++ 코드를 Java에서 JNI를 통해 호출할 수 있습니다.
Java 언어 고유의 비효율성은 주로 다음과 같습니다.
- 모든 개체가 힙에 할당됩니다.스택 할당과 유사하게 수행되는 '범프 할당'을 사용하는 최신 JVM에서는 할당이 매우 빠르지만 가비지 컬렉터의 호출로 인해 여전히 성능에 부정적인 영향을 미칠 수 있습니다.최신 JIT 컴파일러는 Oracle JDK 6 이후 이스케이프 분석 또는 이스케이프 탐지를 통해 이 문제를 어느 정도 완화하여 일부 개체를 스택에 할당합니다.
- 효율적인 데이터베이스 시스템이나 메시징 라이브러리 등 퍼포먼스가 중요한 프로젝트에서는 다음과 같은 내부 비공식 API를 사용해야 했습니다.
sun.misc.Unsafe
수동 리소스 관리에 액세스하여 스택 할당을 수행할 수 있습니다.의사 패킷을 효과적으로 조작할 수 있습니다. - 표준 컨테이너를 사용하더라도 많은 런타임 주조가 필요할 경우 성능 저하가 발생합니다.단, 이러한 캐스트의 대부분은 JIT 컴파일러에 의해 정적으로 제거됩니다.
- 안전 보장은 런타임 비용으로 제공됩니다.예를 들어 컴파일러는 코드에 적절한 범위 체크를 넣어야 합니다.범위 체크로 각 어레이의 접근을 보호하는 것은 효율적이지 않기 때문에 대부분의 J는IT 컴파일러는 정적으로 또는 내부 루프에서 컴파일러를 이동함으로써 이러한 컴파일러를 배제하려고 합니다(단, 대부분의 네이티브 C++ 컴파일러는 옵션으로 범위 체크를 사용할 경우 같은 처리를 합니다).
- 낮은 수준의 세부 정보에 접근할 수 없기 때문에 개발자는 컴파일러가 [21]할 수 없는 프로그램을 개선할 수 없습니다.
- Java에서 모든 사용자 정의 유형에 대해 참조 시맨틱을 의무적으로 사용하면 캐시 누락(예: 캐시 스레싱)이 빈번하게 발생할 수 있는 불필요한 메모리 지시(또는 점프)가 발생할 수 있습니다.또한 캐시 최적화는 보통 캐시 인식 또는 캐시 오비스의 데이터 구조 및 알고리즘을 통해 성능을 대폭 향상시킬 수 있을 뿐만 아니라 많은 캐시 평가 알고리즘의 특징이며, 따라서 최적화의 가장 중요한 형태 중 하나인 시간 복잡성 저하를 방지할 수 있습니다.Java에서 요구되는 ereference-semantics는 (프로그래머나 JIT 컴파일러에 의해) 실제로 그러한 최적화를 실현하는 것을 불가능하게 만든다.
- 가비지 컬렉션([22]이러한 자동 메모리 관리 형식)은 메모리 [23]오버헤드를 발생시킵니다.
그러나 Java의 디자인에는 많은 이점이 있습니다.그 중 일부는 깨달았고 일부는 이론화되었을 뿐입니다.
- Java 가비지 컬렉션은 메모리 할당에 malloc/new를 일반적으로 사용하는 것보다 캐시 일관성이 더 좋을 수 있습니다.그러나 양쪽 할당자가 힙을 균등하게 fragment화하고 어느 쪽도 더 나은 캐시 인접성을 나타내지 않는다는 인수가[weasel words] 존재합니다.단, C++에서는 히프상의 단일 오브젝트의 할당은 드물며, 일반적으로 STL 컨테이너를 통해 또는 작은 오브젝트 [24][25]할당자를 사용하여 블록에 대량의 단일 오브젝트가 할당됩니다.
- 런타임 컴파일은 코드를 보다 효과적으로 개선하기 위해 코드가 실행되고 있는 플랫폼에 대한 정보를 사용할 수 있습니다.그러나 대부분의 최첨단 네이티브(C, C++ 등) 컴파일러는 주어진 [26]시스템의 완전한 계산 능력을 사용하기 위해 여러 코드 경로를 생성합니다.또한 네이티브 컴파일러가 멀티플랫폼 JVM 배포보다 아키텍처별 최적화 및 명령 집합을 더 잘 활용할 수 있다는 반론을 제기할 수 있습니다.
- JIT 컴파일러는 가상 콜의 가능한 모든 타겟에 대해 보다 많은 정보를 가지고 있기 때문에 런타임 컴파일러는 정적 컴파일러보다 더 적극적인 가상 함수 인라인화를 가능하게 합니다.현재 이용 가능한 JVM 구현은 대부분의 단형, 대부분 단형 및 이형 콜을 인라인화하는 데 문제가 없으며, Java [27]7에 추가된 최근 호출 동적 기능 확장 덕분에 인라인 및 메가모픽 콜에 대한 연구가 진행 중입니다.인라인은 루프 벡터화 또는 루프 언롤링과 같은 추가적인 최적화를 가능하게 하여 전체적인 성능을 크게 향상시킬 수 있습니다.
- Java에서는 스레드 동기화가 언어에 내장되어 있기 때문에 JIT 컴파일러는 이스케이프 분석을 통해 잠재적으로 [28]순진한 멀티 스레드 코드의 성능을 크게 향상시킬 수 있습니다.
또, C++ 에서는 몇개의 퍼포먼스 문제가 발생합니다.
- 포인터가 임의의 주소를 가리킬 수 있도록 하면 포인터 에일리어스의 가능성이 있기 때문에 최적화가 어려워질 수 있습니다.
- C++의 같은 클래스 템플릿의 다양한 인스턴스화에서 생성된 코드는 공유되지 않기 때문에(Java의 타입 삭제 제네릭과 마찬가지로) 템플릿을 과도하게 사용하면 실행 가능한 코드 크기가 크게 증가할 수 있습니다(코드 블러트).단, 함수 템플릿은 적극적으로 삽입되어 있기 때문에 코드 사이즈를 줄일 수 있지만 컴파일러에 의한 보다 적극적인 정적 분석과 코드 최적화를 가능하게 하여 많은 경우 비템플릿 코드보다 효율적입니다.이와는 대조적으로 Java 제네릭은 일반화되지 않은 코드보다 효율성이 떨어집니다.
- 기존의 C++ 컴파일러에서는 동적 링크는 C++에서 코드를 생성하고 최적화한 후에 실행되므로 서로 다른 동적 모듈에 걸친 함수 호출을 인라인화할 수 없습니다.그러나 MSVC 및 Clang+LLVM과 같은 최신 C++ 컴파일러는 모듈을 중간 형식으로 컴파일하여 최종 링크 단계에서 인라인화할 수 있는 링크 시간 코드 생성 옵션을 제공합니다.
언어의 공식 표준 및 참조
언어 사양
C++ 언어는 ISO/IEC JTC1/SC22/WG21 위원회에서 발행되는 ISO 표준인 ISO/IEC 14882에 의해 정의됩니다.C++17의 최신 표준화 후 초안도 이용할 수 있습니다.[29]
C++ 언어는 C++ 표준 위원회라는 개방형 운영 위원회를 통해 발전합니다.위원회는 C++ Bjarne Strostrup의 크리에이터, 소집자인 Herb Sutter 및 많은 업계 대표자와 사용자 그룹(즉, 이해관계자)을 포함한 다른 저명한 인사들로 구성되어 있습니다.개방형 위원회이기 때문에 누구나 다음 표준 및 기술 사양 릴리스에 자유롭게 참여하고 제안서를 제출할 수 있습니다.위원회는 과거 엄격한 검토 프로세스와 논의로 인해 새로운 표준 발표(1998년, 2003년, 2011년) 사이의 지연이 길어졌지만, 현재는 몇 년마다 새로운 표준을 발표하는 것을 목표로 하고 있다.
Java 언어는 Oracle에서 발행하는 Java Language [30]Specification에 의해 정의됩니다.
자바 언어가 계속 과정은 자바 커뮤니티 프로세스라고 불리는을 통해서 세계의 프로그래밍 커뮤니티 사람들과 조직의 자바 커뮤니티 members[31일]—which 적극적으로 언어의 향상으로 벌이고 있는 그룹-에 의해, 대중의 요청이 자바 규격 의뢰- 하는 바를 보냄으로써 나타내면서 진화한다.빠공식 및 공개 리뷰를 작성한 후 해당 언어로 통합합니다.
Java에 대한 확고한 표준의 결여와 그 사양의 다소 변동성이 있는 성질은 새로운 언어와 라이브러리 기능의 추가에 있어 보다 안정성과 보수성을 원하는 이해관계자들에 의해 끊임없이 비판의 원인이 되어 왔습니다.반대로 C++ 위원회도 그 반대의 이유로 끊임없이 비판을 받고 있다. 즉, 너무 엄격하고 보수적이며 새로운 버전을 출시하는 데 시간이 너무 오래 걸린다는 것이다.
상표
"C++"는 어떤 회사 또는 조직의 상표도 아니며 개인 [32]소유도 아닙니다."Java"는 Oracle [33]Corporation의 상표입니다.
레퍼런스
- ^ "Unsigned Integer Arithmetic API now in JDK 8". Archived from the original on 25 February 2017. Retrieved 17 March 2014.
- ^ "The Java Tutorials: Passing Information to a Method or a Constructor". Oracle. Retrieved 17 February 2013.
- ^ 를 클릭합니다"The Java Tutorials: Object as a Superclass". Oracle. Retrieved 17 February 2013..
- ^ "XMPP Software » Libraries". xmpp.org. Retrieved 13 June 2013.
- ^ Robert C. Martin (January 1997). "Java vs. C++: A Critical Comparison" (PDF). Archived from the original (PDF) on 11 May 2008. Retrieved 15 December 2007.
- ^ "Reference Types and Values". The Java Language Specification, Third Edition. Retrieved 9 December 2010.
- ^ Horstmann, Cay; Cornell, Gary (2008). Core Java. Vol. I (Eighth ed.). Sun Microsystems. pp. 140–141. ISBN 978-0-13-235476-9.
Some programmers (and unfortunately even some book authors) claim that the Java programming language uses call by reference for objects. However, that is false. Because this is such a common misunderstanding, it is worth examining a counterexample in some detail... This discussion demonstrates that the Java programming language does not use call by reference for objects. Instead object references are passed by value.
- ^ Deitel, Paul; Deitel, Harvey (2009). Java for Programmers. Prentice Hall. p. 223. ISBN 978-0-13-700129-3.
Unlike some other languages, Java does not allow programmers to choose pass-by-value or pass-by-reference—all arguments are passed by value. A method call can pass two types of values to a method—copies of primitive values (e.g., values of type int and double) and copies of references to objects (including references to arrays). Objects themselves cannot be passed to methods.
- ^ "Semantics of Floating Point Math in GCC". GNU Foundation. Retrieved 20 April 2013.
- ^ "Microsoft c++ compiler, /fp (Specify Floating-Point Behavior)". Microsoft Corporation. Retrieved 19 March 2013.
- ^ "Java Language Specification 4.3.1: Objects". Sun Microsystems. Retrieved 9 December 2010.
- ^ 프로그래밍 언어 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/
- ^ Satish Chandra Gupta, Rajeev Palanki (16 August 2005). "Java memory leaks – Catch me if you can". IBM DeveloperWorks. Archived from the original on 22 July 2012. Retrieved 2 April 2015.
{{cite web}}
: CS1 maint: 작성자 파라미터 사용(링크) - ^ Veljko Krunic의 Java 메모리 누전 수정 방법(2009년 3월 10일)
- ^ stackoverflow.com에서 Java를 사용한 메모리누전 생성
- ^ http://en.cppreference.com/w/cpp/language/type_alias
- ^ http://en.cppreference.com/w/cpp/language/variable_template
- ^ 부스트 타입 특성 라이브러리
- ^ Java 제네릭은 튜링 완료
- ^ Clark, Nathan; Amir Hormati; Sami Yehia; Scott Mahlke (2007). "Liquid SIMD: Abstracting SIMD hardware using lightweight dynamic mapping". Hpca'07: 216–227.
- ^ Hundt, Robert (27 April 2011). "Loop Recognition in C++/Java/Go/Scala" (PDF). Stanford, California: Scala Days 2011. Retrieved 17 November 2012.
Java shows a large GC component, but a good code performance. [...] We find that in regards to performance, C++ wins out by a large margin. [...] The Java version was probably the simplest to implement, but the hardest to analyze for performance. Specifically the effects around garbage collection were complicated and very hard to tune; 318 kB
- ^ Matthew Hertz, Emery D. Berger (2005). "Quantifying the Performance of Garbage Collection vs. Explicit Memory Management" (PDF). OOPSLA 2005. Archived from the original (PDF) on 6 July 2017. Retrieved 15 March 2015.
In particular, when garbage collection has five times as much memory as required, its runtime performance matches or slightly exceeds that of explicit memory management. However, garbage collection’s performance degrades substantially when it must use smaller heaps. With three times as much memory, it runs 17% slower on average, and with twice as much memory, it runs 70% slower.
- ^ Alexandrescu, Andrei (2001). Addison-Wesley (ed.). Modern C++ Design: Generic Programming and Design Patterns Applied. Chapter 4. pp. 77–96. ISBN 978-0-201-70431-0.
- ^ "Boost Pool library". Boost. Retrieved 19 April 2013.
- ^ 런타임 퍼포먼스 체크를 위한 IA-32 아키텍처 프로세서의 타깃팅
- ^ "Fixing The Inlining "Problem" by Dr. Cliff Click Azul Systems: Blogs". Archived from the original on 7 September 2011. Retrieved 23 September 2011.
- ^ Java 개발자를 위한 Oracle 기술 네트워크
- ^ "Working Draft, Standard for Programming Language C++" (PDF).
- ^ 자바 언어 사양
- ^ 자바 커뮤니티 프로세스 - 참여 - JCP 멤버
- ^ Bjarne Strostrup의 FAQ: C++를 소유하고 계십니까?
- ^ ZDNet: Oracle이 Sun을 인수하여 2010년 4월 10일 Wayback Machine에서 Java Archived를 소유하게 되었습니다.
외부 링크
- C++와 Java의 차이점
- 객체 지향 메모리 관리: Java와C++
- 제2장:Java와 C의 차이점, David Flanagan의 Nutshell에 있는 Java와 차이점
- 자바와 C++ 자원 관리 비교 - 포괄적인 문서와 예시
- Java 대 C 성능... 다시... - Java와 C/C++의 퍼포먼스 차이에 대한 자세한 설명
- Hyperpoly - Java와 C++의 비교