`
_Yggd
  • 浏览: 89821 次
  • 性别: Icon_minigender_1
  • 来自: 西安
社区版块
存档分类
最新评论

java和C++的简单的对比

 
阅读更多

曾经听过有人不看好Java这种语言,(当然这个人对于C++和C的挺有研究的)认为将程序员的思路以及编程时候的坏习惯都惯出来了,认为java语言能实现的功能C++都能实现(这是废话),还有就是它的效率确实成为大家攻讦的理由,但是我认为一门编程语言为大众所接受并且风靡这么多年毕竟有它的原因,不能一言以蔽之

当然现在的java虚拟机的效率堪比C++的效率,现在就将二者的比较贴出来,供各位观看:

 

 

源:http://zh.wikipedia.org/wiki/Java和C%2B%2B的對照

C++和Java语言之间的不同可以追溯到它们各自的传统,它们有着不同的设计目标。

  • C++ 被设计成主要用在系统性应用程式设计上,对C语言进行了扩展。对于C语言这个为执行效率设计的程序式程式设计语言, C++ 特别加上了以下这些特性的支持:静态类型面向对象程序设计的支持、异常处理RAII以及泛型。另外它还加上了一个包含泛型容器和算法的C++函式库
  • Java 最开始是被设计用来支持网络计算。它依赖一个虚拟机在来保证安全可移植性。Java 包含一个可扩展的库用以提供一个完整的的下层平台的抽象。Java 是一种静态面向对象语言,它使用的语法类似C++,但与之不兼容。为了使更多的人使用更易用的语言,它进行了全新的设计。

不同的开发目标导致 C++ 和 Java 这两种语言的不同的规则以及设计上的平衡点不同。 如下列出不同点:

C++ Java
除了一些比较少见的情况之外和C语言相容 没有对任何之前的语言向前相容。但在语法上受 C/C++ 的影响很大
一次编写多处编译 一次编写多处运行
允许程序式程式设计面向对象程序设计 鼓励(或者说必须)面向对象的程式设计方式
允许直接调用原生的系统库 要通过JNI调用, 或者 JNA
能直接使用底层系统接口 在一个保护模式下的虚拟机中运行
只提供物件的类型和类型名 反射的, 允许元程式设计和运行时的动态生成代码
有多种二进制相容标准 (例如:微软和Itanium/GNU) 一种二进制相容标准,允许运行时库的正确性检查
可选的自动边界检查. (例如: vector 和 string 这两个容器的 at() 方法) 一般都有做边界检查。HotSpot (java)(Sun 的虚拟机实现) 可以去掉边界检查
支持原生的无符号数学运算 不支持原生的无符号数学运算
对所有的数字类型有标准的范围限制,但字节长度是跟实现相关的。标准化的类型可以用 typdef 定义 (uint8_t, ..., uintptr_t) 在所有平台上对所有的基本类型都有标准的范围限制和字节长度
支持指针,引用,传值调用 基本类型总是使用传值调用。物件以可以为空的参考的方式传递(相当于在C++里使用指向 class 或者 struct 参数的指标)。[1]
显式的内存管理,但有第三方的框架可以提供垃圾搜集的支持。支持析构函式。 自动垃圾搜集(可以手动触发)。没有析构函式的概念,对 finalize() 的使用是不推荐的
支持类class,结构struct,联合union,可以在堆栈或者里为它们动态分配内存 只支持类别,只在堆栈中为物件分配内存。Java SE 6在栈为一些物件分配内存的使用了逃逸分析的优化方法
允许显式的覆盖(也叫重写)类型 严格的类型安全,除了变宽的类型转换。Java 1.5 开始支持自动类型包装和解包装(Autoboxing/Unboxing)
C++函式库包括:语言支持,诊断工具,常用工具,字符串,本地化,容器,算法,迭代器,数值,输入/输出,C函式库。Boost库提供了更多的功能,包括执行绪和网络I/O。使用者必须在一大堆(大部分互相不相容)第三方GUI或者其他功能库中进行选择 函式库在每次 Java 发布新版本的时候都会更新并增强功能。1.6版本支持:本地化,日志系统,容器和迭代器,算法,GUI 程式设计(但没有用到系统的GUI),图形,多执行绪,网络,平台安全,自省机制,动态类别加载,阻塞和非阻塞的I/O,对于XMLXSLTMIDI也提供了相关接口或者支持类别,数据库,命名服务(例如LDAP),密码学,安全服务(例如 Kerberos),打印服务,WEB 服务。SWT 提供了一个系统相关的GUI的抽象
大部分运算符可以运算符重载 运算子的意义一般来说是不可变的,例外是 + 和 += 运算子被字符串多载了
完全的多重继承,包括虚拟继承 类别只允许单继承,需要多继承的情况要使用接口
支持编译期模板 泛型被用来达到和C++模板类似的效果,但由于类型消除它们不能在编译期间从代码被编译成字节码
支持函式指标,函式物件,lambda(C++11)和接口 没有函式指标机制。替代的概念是接口,Adapter 和 Listener也是被广泛使用的
没有标准的代码内嵌文档机制。不过有第三方的软件(例如 Doxygen) Javadoc 标准文档生成系统
const 关键字用来定义不可改变的常量和成员函式 final 提供了一个限制版本的 const,等价于 type* const 的物件指标或者const的基本类型数据。没有 const 成员函式,也没有const type* 指标的等价物
支持 goto 语句 支持循环标签(label)和语句块
源代码可以写成平台无关的(可以被 WindowsBSDLinuxMac OS XSolaris等编译,不用修改),也可以写成利用平台特有的特性。通常被编译成原生的机器码 被编译成Java虚拟机的字节码。和Java平台相关,但是源代码一般来说是不依赖操作系统特有的特性的

C++ 是一门强大的语言,设计用在系统程式设计方面。Java语言是设计成简单易用易学习,并有一个强大的跨平台的库。Java函式库对一个函式库来说相当的大。但Java并不会提供所在平台的所有特性和接口。C++函式库简单健壮,提供容器关联数组的支持。[2]

语言特性[编辑]

语法[编辑]

  • Java语法上下文无关文法,可以用一个简单的LALR语法分析器来分析.而分析C++就复杂多了;例如 Foo<1>(3); ,如果 Foo 是一个变量,那么它是一个比较的表达式,但如果 Foo 是一个类模板的名字,那么它会创建一个对象.
  • C++允许名字空间级别的常量,变量和函数. 而所有这样的 Java 声明必须在一个类或者接口当中.
  • 在 C++ 的声明中,一个类名可以用来声明一个此类对象的值. Java 里没办法做到这点. 在Java里对象不是值. 在 Java 的声明中,一个类名声明的是对此类的一个对象的引用. 而在 C++ 里与之等价的做法是用 "*" 来声明一个指针.
  • 在 C++ 里,"."操作符将一个对象作为一个左操作参数来访问这个对象的成员. 因为对象在 Java 里不是值,所有的对象都通过引用来访问,刚才的做法在 Java 里是无法实现的. 在 Java 里,"." 操作符是将一个对象的引用作为左操作参数来访问这个对象的成员.在C++中和这种做法等价的是 "->".
C++ Java
class Foo {          // 声明 Foo 类
public:
    int x;           // 成員變量
 
    Foo(): x(0) {    // Foo 的构造函数Constructor for Foo,
    }                //  初始化 x
 
    int bar(int i) { // 成员函数 bar()
        return 3*i + x;
    }
};
class Foo {               // 定义类 Foo
    public int x = 0;     // 成员变量,
                          //  以及其值的初始化
    public Foo() {        // Foo的 构造函数
    }
 
    public int bar(int i) {// 成员方法 bar()
        return 3*i + x;
    }
}
Foo a;
// 声明 a 为一个 Foo 类的对象值,
// 使用其缺省的构造函数
// 如果你想要用其他的构造函数,
// 你可以用 "Foo a(args);"
Foo a;
// 声明 a 为一个 Foo 类的对象的引用
a = new Foo();
// 使用缺省的构造函数初始化
// 如果你想要用其他的构造函数,
// 你可以用 "Foo a = new Foo(args);"
Foo b = a;
// 拷贝 a 的内容到一个新的 Foo 类的变量 b 当中;
// 另一种可以选择的语法是 "Foo b(a)"
Foo b = a.clone();
// 拷贝所有a这个实例的成员到b,当且仅当,
// Foo 实现了一个 public 的 clone() 方法,
// 并且 clone() 返回一个新的这个对象的拷贝
a.x = 5; // 修改 a 对象
a.x = 5; // 修改 a 对象
cout << b.x << endl;
// 输出 0,因为 b 和 a 是两个对象
System.out.println(b.x);
// 输出 0,因为 b 和 a 是两个对象
Foo *c;
// 声明 c 为指向一个 Foo 类对象的指针(初始值是
// 未定义的;可能指向任何地方)
Foo c;
// 声明 c 为一个指向 Foo 对象的指针
// (如果 c 是一个类的成员,那么初始值为空;
// 如果 c 是一个局部变量那么你在使用之前必须
// 对它进行初始化)
c = new Foo();
// 将 c 绑定为一个新的 Foo 对象的引用
c = new Foo();
// 将 c 绑定为一个新的 Foo 对象的引用
Foo *d = c;
// 将 d 绑定为和 c 同一个对象的引用
Foo d = c;
// 将 d 绑定为和 c 同一个对象的引用
c->x = 5;
// 修改 c 指向的对象
c.x = 5;
// 修改 c 指向的对象
a.bar(5);  // 对 a 调用 Foo::bar()
c->bar(5); // 对 *c 调用 Foo::bar()
a.bar(5); // 对 a 调用 Foo.bar()
c.bar(5); // 对 c 调用 Foo.bar()
cout << d->x << endl;
// 输出 5,因为 d 引用的对象和 c 一样
System.out.println(d.x);
// 输出 5,因为 d 引用的对象和 c 一样
  • 在 C++ 里,声明一个指向常量的指针是可能的, 也就是说, 你不能修改这个指针指向的对象的内容. 函数和方法也都保证不会修改用 "const" 关键字的指针指向的对象的内容,是强制常量正确性的. 在 Java 里这是不可能做到的. 你可以声明一个引用为 "final"(就像在 C++ 里声明一个 "const" 指针), 但这只是阻止你重新绑定这个引用; 你还是可以修改这个 "final" 引用指向的对象的.
C++ Java
const Foo *a; // 你不能通过 a 修改 a 指向的对象
final Foo a; // 你可以通过 a 修改 a 指向的对象
a = new Foo();
a = new Foo(); // 只能在构造函数里
a->x = 5;
// 非法
a.x = 5;
// 合法, 你仍然可以修改这个对象
Foo *const b = new Foo();
// 你可以声明一个 "const" 指针
final Foo b = new Foo();
// 你可以声明一个 "final" 引用
b = new Foo();
// 非法, 你不能对它再次绑定
b = new Foo();
// 非法, 你不能对它再次绑定
b->x = 5;
// 合法,你还是可以修改这个对象
b.x = 5;
// 合法,你还是可以修改这个对象
  • C++ 支持 goto 语句; Java 强制结构化流程控制structured control flow), 依赖break标签 和 continue标签 语句来提供类似于 goto 的部分功能. 一些评论者指出这些标签化的流程控制打破了结构化编程的单退出点的特点.[3]
  • C++ 提供了一些 Java 缺乏的低级特性. 在 C++ 里, 指针可以用来操作特定的内存位置, 这是在写低级操作系统模块的时候必须用到的. 类似的, 许多 C++ 编译期支持内联汇编,在 Java 里, 这样的代码只能放在外来的库中,而且在调用的时候只能通过JNI来访问这些外来库提供的接口.

语义[编辑]

  • C++ 允许给函数/方法的参数设置缺省值, Java 不提供这个特性. 但是方法重载可以达到同样的效果.
  • C++ 里最小的编译单位是一个函数; Java 里最小的编译单位是一个类. 在 C++ 里, 函数可以被单独编译. 在 Java 里, 要编译和维护单独的方法需要把它们移到超类子类或者使用其他的代码重构的技巧.
  • C++ 允许基本类型之间的一些隐式的转换, 也允许程序员对于用户自定义类型相关的隐式转换规则. 在 Java 里, 只有基本类型之间变宽类型的转换可以是隐式的; 其余的转换需要显式的类型转换语法.
    • 这造成的一个后果是,虽然在 Java 和 C++ 里循环的条件(ifwhile 和 for 里的退出条件)预期的都是一个布尔表达式, 但 if(a = 5) 这样的代码在 Java 里会导致编译错误,因为没有从整型到布尔的隐式变窄转换. 如果代码是 if(a == 5) 的输错的情况那么是很方便发现这个错误的. 而目前的 C++ 编译器一般来说只会针对这种情况产生一个警告.
  • 对于传参数给函数的情况, C++ 支持引用传递值传递. 在 Java 里, 参数总是值传递的.[4] 但在 Java 里,所有的非基本类型的值都只是对于对象的引用 (用 C++ 的术语来说, 它们是智能指针). 对象在 Java 里不是作为值直接被使用的,只有对象的引用可以被直接操作; 习惯于将对象当做值直接使用的 C++ 开发者经常会把这个跟引用传递搞混.
  • Java 内建的类型在字节宽度和取值范围上是被虚拟机定义好的; 在 C++ 里, 内建的类型有定义一个最小取值范围, 但是其他的部分(字节宽度)可以被映射成具体平台上支持的原生类型.
    • 举个例子, Java 字符是16位的Unicode字符, 字符串是由这样的字符组成的序列. C++ 提供窄和宽两种字符,但实际的字符宽度是和平台相关的, 视所用的字符集而定. 字符串可以由这两种字符中的一种组成.
  • 浮点数及其操作的精度和舍入方式在 C++ 里是平台相关的. Java 提供了一个可选的严格的浮点数模型,保证跨平台的一致性,不过可能会导致运行时效率比较差.
  • 在 C++ 里, 指针可以作为内存地址直接操作. Java 没有指针 — 它只有对象引用和数组引用,这两者都不允许直接用来访问内存地址. 在 C++ 里可以构造一个指向指针的指针,而 Java 的引用只能指向对象.
  • 在 C++ 里, 指针可以指向函数或者方法(函数指针). 在 Java 里的等价物是对象或者接口的引用.
  • 虽然有使用栈内存分配的对象, C++ 还是支持区域资源管理, 一个用来自动管理内存和其他系统资源的技术,此技术支持确定性对象销毁(deterministic object destruction). 不过,区域资源管理在 C++ 里是不被保证的;它只是一个设计模式,所以需要依赖程序员遵守相关的规则. Java 通过使用垃圾搜集来支持自动内存管理,但对于其他的系统资源(窗口,通讯端口,线程),如果垃圾搜集器无法决定它们是否不再被用到,那通常还是需要显式的释放的.
  • C++ 的用户可自定义操作符重载的特性在 Java 里是不支持的. 唯一在 Java 里可以重载的操作符是 "+" 和 "+=" 操作符, 在字符串里重载为连接字符串.
  • Java 的标准应用程序接口支持反射动态加载任意代码.
  • C++ 支持静态和动态的库连接.
  • Java 支持泛型, 其主要目的是提供类型安全的容器. C++ 支持模板, 在泛型编程方面提供了更强的支持.
  • Java 和 C++ 都对基本类型(也叫"内建"类型)和用户自定义类型(也叫"复合"类型). 在 Java 里, 基本类型只有值的语义,复合类型只有引用的语义. 在 C++ 里所有的值都有值语义,可以创建对于任何类型的引用,这样就允许通过引用语义来操作对象.
  • C++ 支持任意类型的多重继承. 在 Java 里一个类只能从单个的类继承而来,但一个类可以实现多个的接口(换句话说,它支持类型的多重继承,但对于实现只能单继承(it supports multiple inheritance of types, but only single inheritance of implementation))。
  • Java 对于类和接口是显式区分的. 在 C++ 里多重继承和纯虚函数使得定义出类似于 Java 的接口的类是可能的,不过会有少许区别.
  • Java 在语言和标准库都对多线程有良好的支持. synchronized 这个 Java 的关键字为了支持多线程应用提供了简单而安全的互斥锁 ,但同步(synchronized)区只能用 LIFO 的顺序离开. Java 也为更高阶的多线程同步提供了健壮而复杂的库. 在 C++ 里没有专门为多线程定义的内存模型; 但第三方库提供了和 Java 差不多的功能; 不过这些 C++ 库之间差异较大,一致性不好.
  • C++ 方法可以声明为虚函数, 虚函数是在运行期根据对象的类型才确定的. C++ 方法缺省情况下不是虚的. 在 Java 里, 方法缺省情况下是虚的, 但可以使用final关键字使之声明为非虚的.
  • C++ 枚举属于基本类型,支持和其他整数类型之间的转换和比较. Java 枚举实际上是类的实例(它们从 java.lang.Enum<E> 扩展而来),象其他的类一样可以定义构造函数,数据成员及方法.

资源管理[编辑]

  • Java 提供了自动化的垃圾搜集. 在 C++ 里内存管理通常通过构造函数,析构函数以及智能指针。C++ 标准允许垃圾搜集,但并不强制要求; 实际使用上垃圾搜集极少被用到. 强制使用自动垃圾搜集导致了在 Java 里编写实时软件是困难的.[3]
  • C++ 可以申请任意的内存块.Java 只能通过对象实例化来申请内存. (注意:在 Java 里, 程序员可以通过创建一个字节数组模拟申请任意的内存块. 不过 Java 数组仍然是对象.)
  • Java 和 C++ 在资源管理上使用不同的习语. Java 主要依赖只能回收内存的垃圾搜集机制,因为该机制如果用于回收使用中的非内存的系统资源可能是非常危险的。而 C++ 主要依赖 RAII (资源的获取就是初始化). 这反映了这两种语言的几方面的不同:
    • 在 C++ 里在栈里申请复合类型的对象是很平常的,一旦退出栈的范围就会被销毁. 在 Java 里复合类型的对象总是在堆里申请的内存,而后被垃圾搜集器搜集 (除非在虚拟机里使用了逃逸分析技术来将堆的内存申请转成栈的.
    • C++ 有析构函数, 而 Java 有finalizer(en:finalizer). 两者都会在对象释放之前被调用, 但是它们有显著的不同. 一个 C++ 对象的析构函数必须被隐式(栈变量对象的情况)或者显式地调用来释放对象. 析构函数在对象释放之前同步地执行. 同步,协调的反初始化以及释放在 C++ 里满足 RAII 的要求. 在 Java 里, 对象的释放是被垃圾搜集器隐式处理的. 一个 Java 对象的 finalizer 在它被最后一次访问之后和在实际释放之前的某个时间点被异步(en:asynchrony)地调用, 这个调用有可能一直不产生. 非常少的对象需要 finalizer; 只有那些在释放前必须保证一些清理工作一定要做的对象来说才是需要的 — 典型的情况是:释放对 JVM 来说是外部的资源. 在 Java 里,企图安全同步的释放某些系统资源,只能用显式的 try/finally 结构来进行.
    • 在 C++ 里是有可能有一个迷途指针的 – 过时的对一个已释放的对象的引用(en:reference (computer science)); 试图使用一个迷途指针的结果是导致程序错误. 在 Java 里, 垃圾搜集器不会销毁一个正在被引用的对象.
    • 在 C++ 里未初始化过的基本类型对象是有可能存在的, Java 强制要做缺省初始化.
    • 在 C++ 里有可能申请了一个对象,但对它没有任何引用. 这样的不可达对象(en:unreachable object)是无法被销毁的,导致了内存泄漏. 作为对比, 在 Java 里一个对象不会被回收直到它变得不可达(对于用户程序来说). (注意: 弱引用(en:weak reference) 是被支持的, 这个特性让 Java 的垃圾搜集器能够识别不同 程度的可达性.) 在 Java 里垃圾搜集阻止了很多内存泄漏的情况, 但某些情况下泄漏仍然是可能的.[5]
    • Java 更容易泄漏非内存资源, 而 C++ 的惯用做法更不会导致这种泄漏.

[编辑]

  • C++ 对于许多平台相关的特性提供了跨平台的访问方式. 从 Java 到原生的操作系统和硬件相关的函数的直接访问需要用到JNI(en:Java Native Interface).

运行时[编辑]

  • C++ 通常来说会直接被编译成机器码,被操作系统直接执行. Java 通常会被编译成字节码,被Java虚拟机解释器或者即时编译器编译成机器码然后执行.
  • 因为表达方式不受限制,低级的 C++ 语言特性(例如:不被检查的数组访问,原始指针,类型双关语(en:type punning))不能在编译期间或者运行期间可靠地被检查. 相关的编程错误会导致低级的缓存溢出段错误(en:segmentation fault). 标准模板库 提供了高级的抽象(例如 vector,list 和 map)来帮助避免这样的错误. 在 Java 里, 低级错误不会发生或者会被JVM检测到并以异常的形式报告给应用.
  • Java 语言在越界访问数组的时候一般来说会对数组进行边界检查(en:bounds checking). 这消除了导致程序不稳定的一个可能因素,但这是以执行速度更慢一些作为代价的. 在一些情况下,编译器分析(en:compiler analysis)可以检测到不必要的边界检查并去掉. C++ 对于原生数组的越界访问没有要求特定的处理, 所以需要对于原生数组确认不越界. 但C++ 标准库里的一部分库象 std::vector 也提供了可选的边界检查. 总的来说, Java 数组是"总是安全;严格限制;开销较多" ,而 C++ 原生数组是"可选的开销; 完全不限制; 有潜在的不安全."

模板 vs. 泛型[编辑]

C++ 和 Java 都提供泛型编程的能力,分别是模板 和 泛型(en:Generics in Java). 虽然它们被创造用来解决类似的问题,有类似的语法,但实际上很不一样.

C++ 模板 Java 泛型
类和函数都可以使用模板. 类和方法都可以使用泛型.
参数可以是任意类型或者整型. 参数只能是能被引用的类型(非基本类型).
在编译的时候对于每种类型生成类或者函数的拷贝. 对于所有类型的参数,只有一个版本的类或者函数生成.
同一个类用不同类型生成的对象在运行期也是不同类型的 编译完成以后类型参数的类型是被消除的; 同一个类用不同类型参数生成的对象在运行期是相同类型的.
想要用到模板类或者函数的实现代码的话必须 include 它(只是声明是不够的). 有一个编译好的类文件里的类或者函数的签名就足以使用泛型了
模板可以被具体化 -- 可以为某个特定的模板参数提供单独的实现. 泛型不能被具体化.
模板参数可以有缺省参数(en:default argument)(只针对对于模板类,模板函数是没有此特性的). 泛型类参数无法拥有缺省参数.
不支持通配符. 返回的类型经常是嵌套的 typedef 形式的. 如果只用一次,那么支持通配符作为类型参数.
不直接支持设置类型参数的边界 (即, 不允许说明类型参数必须为某个类型的子类/父类), 但超编程提供了这个特性[6] 支持类型参数边界, 分别以 "extends" 和 "super" 来定义上界和下界; 同时允许定义类型参数之间的继承关系
允许生成有参模板的类的实例 (如 foo = new Foo<T>, T 为参数) 不允许生成有参模板类的实例 (除非使用反射)
模板类的类型参数可以用在 static 方法和变量上. 泛型类的类型参数无法用在 static 方法和变量上.
static 变量不在在不同的类型参数生成的类之间共享. static 变量在不同类型参数生成的类的对象之间是共享的.
泛型类和函数在声明时不强制类参数的类限制. 使用错误的类参数会导致模板代码"不工作". 值得注意的是, 如果使用了错误的参数, 则错误信息将出现在定义模板的代码处 (而非调用模板的代码处), 说明 "不支持以该类型作为参数来实例化模板". 这种错误信息往往难以帮助人们找出真正的问题所在 (编程时究竟使用了何种 "错误的" 参数). 因此, 模板类或者函数的正确使用更依赖于正确的文档. 超编程以额外的代价提供了这些特性. 泛型类和函数在声明的时候强制了类参数的类限制(Generic classes and functions can enforce type relationships for type parameters in their declaration). 使用一个错误的参数会在使用它的时候导致一个类错误. 在泛型代码里操作和参数化类型只能按声明的时候保证安全的方式来使用. 这用失去弹性的代价来换取好得多的类型方面的安全性.
模板是图灵完全的 (参见 模板超编程). 泛型不是图灵完全的.

杂项[编辑]

  • Java 和 C++ 在使代码在不同的文件分开方面使用了不同的技术. Java 使用了一个包系统,这个系统对所有的程序都要指定了文件名和路径. 在 Java 里, 编译器负责导入可执行的类文件. C++ 使用了头文件源代码的包含系统来在不同的文件共享声明.
  • 编译好的 Java 代码一般来说比 C++ 文件小,因为Java字节码(en:Java bytecode)一般来说比机器码要更紧凑[来源请求],Java 程序都不是静态链接的.
  • C++ 编译多了一个文本预处理过程, Java 是没有的. 因此一些使用者在他们的编译过程之前增加了一个预处理的过程,这样能更好的支持需要条件编译的情况.
  • 两个语言里数组都是定长的. 在 Java 里, 数组是一等对象(en:first-class object), 而在 C++ 里它们只是它们的基本类型元素的连续的序列, 经常用一个指向第一个元素的指针和一个可选的长度来引用. 在 Java 里, 数组是被边界检查的,而且知道它们的长度, 而在 C++ 里你可以将任意的序列当成一个数组. C++ 和 Java 都提供了相关的容器类(分别为std::vector 和 java.util.ArrayList),可以改变大小.
  • Java 的除法和模除操作符是定义成零截断的. C++ 没有定义这两个操作符是零截断的还是"负无穷截断"的. 在 Java 里-3/2 总是得到 -1, 但一个 C++ 编译器可能会返回 -1 或 -2, 视平台而定. C99 定义了和 Java 一样的除法方式. 两种语言都保证对于所有的 a 和 b(b!=0)(当 a 和 b都是整型的时候)(a/b)*b + (a%b) == a. C++ 版本有时候会更快,因为它允许直接使用处理器的截断方式.
  • 整型的长度在 Java 里是已定义好的(int 为 32-bit, long 为 64-bit), 而在 C++ 里整型和指针的长度是和编译器以及应用二进制接口相关的. 因此仔细编写的 C++ 代码可以利用64位处理器的能力而又可以在32位处理器上工作. 但是需要很仔细的用可移植的方式编写. 作为对比, Java 的固定整型大小使得程序员无法做到这样,没办法利用处理器的字长会导致 Java 在64位处理器上表现较差.

性能[编辑]

想运行一个编译好的 Java 程序,计算机上要运行JVM;而编译好的 C++ 程序不需要额外的应用。比较早期的 Java 版本在性能上比静态编译的语言如 C++ 差得很多,这是因为用 C++ 是直接编译成一些机器指令,而当 Java 编译成字节码以后用 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 要快,[7] 有几个数值方面的基准测试的研究争辩说 Java 在某些情况下可能会比 C++ 的性能好得多。[8][9][10] 但有人说数值方面的基准测试对于语言的评估是不合适的,因为编译器都可以做相关的优化,甚至可能将被测试的代码彻底删除。[11][12][13] 如果涉及到一个真正现实应用的程序,Java 会因为很多原因导致性能变差:[14][15][16]

  • 所有的对象都在堆里被申请。对于使用小对象的函数来说会导致很大的性能损失,因为在栈里申请内存几乎没有性能损失。
  • 方法缺省是虚的。这对于小对象来说会因为虚表增加好几倍的内存使用。它也会引起性能损失,因为 JIT 编译器不得不对查虚表的过程做额外的优化。
  • 即使使用标准的容器依然会有很多的类型转换,这会引起性能损失,因为需要遍历整个继承树。
  • 虚拟机更进一步增加了内存的使用,因此降低了内存的局部性,增加了缓存命中失败率,从而导致整个程序变慢。
  • 缺乏低级细节的操作方式使得开发者无法将程序进一步优化,因为编译器不支持。[17]

有人争论说,和 Java 相比 C++也有很多劣势:

  • 指针使得优化变得困难,因为它们可能指向任意的数据。当然现在这一点也并非完全正确,因为一些现代的编译器引入了 "严格别名" 的规则 [18] 并且支持 C99 的关键字 restrict,从而严格限制了指针的使用,使其只能用于指向已知的变量 [19]
  • Java 的垃圾搜集和使用malloc/new来申请内存相比能拥有更好的缓存连贯性,因为它的申请一般来说是顺序的。然而,始终有争论认为二者同样会导致内存的“零碎化”(即多次分配和回收之后内存空间会变得不连续),且并没有哪一个比对方有更明显的缓存优势。
  • 运行时编译可能可以更好的优化代码,因为可以利用运行时的额外的信息,例如知道代码是在什么样的处理器上运行。然而当今的情况也并非完全如此,因为目前最先进的 C++ 编译器也会针对不同系统生成不同的目标代码,以期充分利用该系统的计算能力 [20]

此外,有争议的是,花在更复杂的 C++ 代码上的 debug 时间太多,用 Java 开发完全可以把这些时间用来优化 Java 代码。当然对于一个给定的程序来说两种语言能优化到什么程度也是一方面。最后,对于处理器负担很重的情况,例如视频渲染,C++ 能直接访问硬件,在同样一个硬件规格下 C++ 总是会比 Java 的表现好很多。

所有权控制[编辑]

C++ 不是任何一个公司或者组织的商标,不被任何个人拥有。[21] Java 是Sun的商标,现在被甲骨文公司拥有。[22]

C++ 语言由ISO/IEC 14882定义,是一个 ISO 标准,由 ISO/IEC JTC1/SC22/WG21委员会发布。 Java 语言由Java Language Specification[1]定义,这是一本Sun公司(现在是甲骨文)出版的书。

分享到:
评论
1 楼 _Yggd 2013-08-23  
源:http://docs.huihoo.com/java/c++_java.html

“作为一名C++程序员,我们早已掌握了面向对象程序设计的基本概念,而且Java的语法无疑是非常熟悉的。事实上,Java本来就是从C++衍生出来的。”

然而,C++和Java之间仍存在一些显著的差异。可以这样说,这些差异代表着技术的极大进步。一旦我们弄清楚了这些差异,就会理解为什么说Java是一种优秀的程序设计语言。本附录将引导大家认识用于区分Java和C++的一些重要特征。

(1) 最大的障碍在于速度:解释过的Java要比C的执行速度慢上约20倍。无论什么都不能阻止Java语言进行编译。写作本书的时候,刚刚出现了一些准实时编译器,它们能显著加快速度。当然,我们完全有理由认为会出现适用于更多流行平台的纯固有编译器,但假若没有那些编译器,由于速度的限制,必须有些问题是Java不能解决的。

(2) 和C++一样,Java也提供了两种类型的注释。

(3) 所有东西都必须置入一个类。不存在全局函数或者全局数据。如果想获得与全局函数等价的功能,可考虑将static方法和static数据置入一个类里。注意没有象结构、枚举或者联合这一类的东西,一切只有“类”(Class)!

(4) 所有方法都是在类的主体定义的。所以用C++的眼光看,似乎所有函数都已嵌入,但实情并非如何(嵌入的问题在后面讲述)。

(5) 在Java中,类定义采取几乎和C++一样的形式。但没有标志结束的分号。没有class foo这种形式的类声明,只有类定义。

class aType()

void aMethod() {/* 方法主体 */}

}

(6) Java中没有作用域范围运算符“::”。Java利用点号做所有的事情,但可以不用考虑它,因为只能在一个类里定义元素。即使那些方法定义,也必须在一个类的内部,所以根本没有必要指定作用域的范围。我们注意到的一项差异是对static方法的调用:使用ClassName.methodName()。除此以外,package(包)的名字是用点号建立的,并能用import关键字实现C++的“#include”的一部分功能。例如下面这个语句:

import java.awt.*;

(#include并不直接映射成import,但在使用时有类似的感觉。)

(7) 与C++类似,Java含有一系列“主类型”(Primitive type),以实现更有效率的访问。在Java中,这些类型包括boolean,char,byte,short,int,long,float以及double。所有主类型的大小都是固有的,且与具体的机器无关(考虑到移植的问题)。这肯定会对性能造成一定的影响,具体取决于不同的机器。对类型的检查和要求在Java里变得更苛刻。例如:

■条件表达式只能是boolean(布尔)类型,不可使用整数。

■必须使用象X+Y这样的一个表达式的结果;不能仅仅用“X+Y”来实现“副作用”。

(8) char(字符)类型使用国际通用的16位Unicode字符集,所以能自动表达大多数国家的字符。

(9) 静态引用的字串会自动转换成String对象。和C及C++不同,没有独立的静态字符数组字串可供使用。

(10) Java增添了三个右移位运算符“>>>”,具有与“逻辑”右移位运算符类似的功用,可在最末尾插入零值。“>>”则会在移位的同时插入符号位(即“算术”移位)。

(11) 尽管表面上类似,但与C++相比,Java数组采用的是一个颇为不同的结构,并具有独特的行为。有一个只读的length成员,通过它可知道数组有多大。而且一旦超过数组边界,运行期检查会自动丢弃一个异常。所有数组都是在内存“堆”里创建的,我们可将一个数组分配给另一个(只是简单地复制数组句柄)。数组标识符属于第一级对象,它的所有方法通常都适用于其他所有对象。

(12) 对于所有不属于主类型的对象,都只能通过new命令创建。和C++不同,Java没有相应的命令可以“在堆栈上”创建不属于主类型的对象。所有主类型都只能在堆栈上创建,同时不使用new命令。所有主要的类都有自己的“封装(器)”类,所以能够通过new创建等价的、以内存“堆”为基础的对象(主类型数组是一个例外:它们可象C++那样通过集合初始化进行分配,或者使用new)。

(13) Java中不必进行提前声明。若想在定义前使用一个类或方法,只需直接使用它即可——编译器会保证使用恰当的定义。所以和在C++中不同,我们不会碰到任何涉及提前引用的问题。

(14) Java没有预处理机。若想使用另一个库里的类,只需使用import命令,并指定库名即可。不存在类似于预处理机的宏。

(15) Java用包代替了命名空间。由于将所有东西都置入一个类,而且由于采用了一种名为“封装”的机制,它能针对类名进行类似于命名空间分解的操作,所以命名的问题不再进入我们的考虑之列。数据包也会在单独一个库名下收集库的组件。我们只需简单地“import”(导入)一个包,剩下的工作会由编译器自动完成。

(16) 被定义成类成员的对象句柄会自动初始化成null。对基本类数据成员的初始化在Java里得到了可靠的保障。若不明确地进行初始化,它们就会得到一个默认值(零或等价的值)。可对它们进行明确的初始化(显式初始化):要么在类内定义它们,要么在构建器中定义。采用的语法比C++的语法更容易理解,而且对于static和非static成员来说都是固定不变的。我们不必从外部定义static成员的存储方式,这和C++是不同的。

(17) 在Java里,没有象C和C++那样的指针。用new创建一个对象的时候,会获得一个引用(本书一直将其称作“句柄”)。例如:

String s = new String("howdy");

然而,C++引用在创建时必须进行初始化,而且不可重定义到一个不同的位置。但Java引用并不一定局限于创建时的位置。它们可根据情况任意定义,这便消除了对指针的部分需求。在C和C++里大量采用指针的另一个原因是为了能指向任意一个内存位置(这同时会使它们变得不安全,也是Java不提供这一支持的原因)。指针通常被看作在基本变量数组中四处移动的一种有效手段。Java允许我们以更安全的形式达到相同的目标。解决指针问题的终极方法是“固有方法”(已在附录A讨论)。将指针传递给方法时,通常不会带来太大的问题,因为此时没有全局函数,只有类。而且我们可传递对对象的引用。Java语言最开始声称自己“完全不采用指针!”但随着许多程序员都质问没有指针如何工作?于是后来又声明“采用受到限制的指针”。大家可自行判断它是否“真”的是一个指针。但不管在何种情况下,都不存在指针“算术”。

(18) Java提供了与C++类似的“构建器”(Constructor)。如果不自己定义一个,就会获得一个默认构建器。而如果定义了一个非默认的构建器,就不会为我们自动定义默认构建器。这和C++是一样的。注意没有复制构建器,因为所有自变量都是按引用传递的。

(19) Java中没有“破坏器”(Destructor)。变量不存在“作用域”的问题。一个对象的“存在时间”是由对象的存在时间决定的,并非由垃圾收集器决定。有个finalize()方法是每一个类的成员,它在某种程度上类似于C++的“破坏器”。但finalize()是由垃圾收集器调用的,而且只负责释放“资源”(如打开的文件、套接字、端口、URL等等)。如需在一个特定的地点做某样事情,必须创建一个特殊的方法,并调用它,不能依赖finalize()。而在另一方面,C++中的所有对象都会(或者说“应该”)破坏,但并非Java中的所有对象都会被当作“垃圾”收集掉。由于Java不支持破坏器的概念,所以在必要的时候,必须谨慎地创建一个清除方法。而且针对类内的基础类以及成员对象,需要明确调用所有清除方法。

(20) Java具有方法“过载”机制,它的工作原理与C++函数的过载几乎是完全相同的。

(21) Java不支持默认自变量。

(22) Java中没有goto。它采取的无条件跳转机制是“break 标签”或者“continue 标准”,用于跳出当前的多重嵌套循环。

(23) Java采用了一种单根式的分级结构,因此所有对象都是从根类Object统一继承的。而在C++中,我们可在任何地方启动一个新的继承树,所以最后往往看到包含了大量树的“一片森林”。在Java中,我们无论如何都只有一个分级结构。尽管这表面上看似乎造成了限制,但由于我们知道每个对象肯定至少有一个Object接口,所以往往能获得更强大的能力。C++目前似乎是唯一没有强制单根结构的唯一一种OO语言。

(24) Java没有模板或者参数化类型的其他形式。它提供了一系列集合:Vector(向量),Stack(堆栈)以及Hashtable(散列表),用于容纳Object引用。利用这些集合,我们的一系列要求可得到满足。但这些集合并非是为实现象C++“标准模板库”(STL)那样的快速调用而设计的。Java 1.2中的新集合显得更加完整,但仍不具备正宗模板那样的高效率使用手段。

(25) “垃圾收集”意味着在Java中出现内存漏洞的情况会少得多,但也并非完全不可能(若调用一个用于分配存储空间的固有方法,垃圾收集器就不能对其进行跟踪监视)。然而,内存漏洞和资源漏洞多是由于编写不当的finalize()造成的,或是由于在已分配的一个块尾释放一种资源造成的(“破坏器”在此时显得特别方便)。垃圾收集器是在C++基础上的一种极大进步,使许多编程问题消弥于无形之中。但对少数几个垃圾收集器力有不逮的问题,它却是不大适合的。但垃圾收集器的大量优点也使这一处缺点显得微不足道。

(26) Java内建了对多线程的支持。利用一个特殊的Thread类,我们可通过继承创建一个新线程(放弃了run()方法)。若将synchronized(同步)关键字作为方法的一个类型限制符使用,相互排斥现象会在对象这一级发生。在任何给定的时间,只有一个线程能使用一个对象的synchronized方法。在另一方面,一个synchronized方法进入以后,它首先会“锁定”对象,防止其他任何synchronized方法再使用那个对象。只有退出了这个方法,才会将对象“解锁”。在线程之间,我们仍然要负责实现更复杂的同步机制,方法是创建自己的“监视器”类。递归的synchronized方法可以正常运作。若线程的优先等级相同,则时间的“分片”不能得到保证。

(27) 我们不是象C++那样控制声明代码块,而是将访问限定符(public,private和protected)置入每个类成员的定义里。若未规定一个“显式”(明确的)限定符,就会默认为“友好的”(friendly)。这意味着同一个包里的其他元素也可以访问它(相当于它们都成为C++的“friends”——朋友),但不可由包外的任何元素访问。类——以及类内的每个方法——都有一个访问限定符,决定它是否能在文件的外部“可见”。private关键字通常很少在Java中使用,因为与排斥同一个包内其他类的访问相比,“友好的”访问通常更加有用。然而,在多线程的环境中,对private的恰当运用是非常重要的。Java的protected关键字意味着“可由继承者访问,亦可由包内其他元素访问”。注意Java没有与C++的protected关键字等价的元素,后者意味着“只能由继承者访问”(以前可用“private protected”实现这个目的,但这一对关键字的组合已被取消了)。

(28) 嵌套的类。在C++中,对类进行嵌套有助于隐藏名称,并便于代码的组织(但C++的“命名空间”已使名称的隐藏显得多余)。Java的“封装”或“打包”概念等价于C++的命名空间,所以不再是一个问题。Java 1.1引入了“内部类”的概念,它秘密保持指向外部类的一个句柄——创建内部类对象的时候需要用到。这意味着内部类对象也许能访问外部类对象的成员,毋需任何条件——就好象那些成员直接隶属于内部类对象一样。这样便为回调问题提供了一个更优秀的方案——C++是用指向成员的指针解决的。

(29) 由于存在前面介绍的那种内部类,所以Java里没有指向成员的指针。

(30) Java不存在“嵌入”(inline)方法。Java编译器也许会自行决定嵌入一个方法,但我们对此没有更多的控制权力。在Java中,可为一个方法使用final关键字,从而“建议”进行嵌入操作。然而,嵌入函数对于C++的编译器来说也只是一种建议。

(31) Java中的继承具有与C++相同的效果,但采用的语法不同。Java用extends关键字标志从一个基础类的继承,并用super关键字指出准备在基础类中调用的方法,它与我们当前所在的方法具有相同的名字(然而,Java中的super关键字只允许我们访问父类的方法——亦即分级结构的上一级)。通过在C++中设定基础类的作用域,我们可访问位于分级结构较深处的方法。亦可用super关键字调用基础类构建器。正如早先指出的那样,所有类最终都会从Object里自动继承。和C++不同,不存在明确的构建器初始化列表。但编译器会强迫我们在构建器主体的开头进行全部的基础类初始化,而且不允许我们在主体的后面部分进行这一工作。通过组合运用自动初始化以及来自未初始化对象句柄的异常,成员的初始化可得到有效的保证。

1045页程序

(32) Java中的继承不会改变基础类成员的保护级别。我们不能在Java中指定public,private或者protected继承,这一点与C++是相同的。此外,在衍生类中的优先方法不能减少对基础类方法的访问。例如,假设一个成员在基础类中属于public,而我们用另一个方法代替了它,那么用于替换的方法也必须属于public(编译器会自动检查)。

(33) Java提供了一个interface关键字,它的作用是创建抽象基础类的一个等价物。在其中填充抽象方法,且没有数据成员。这样一来,对于仅仅设计成一个接口的东西,以及对于用extends关键字在现有功能基础上的扩展,两者之间便产生了一个明显的差异。不值得用abstract关键字产生一种类似的效果,因为我们不能创建属于那个类的一个对象。一个abstract(抽象)类可包含抽象方法(尽管并不要求在它里面包含什么东西),但它也能包含用于具体实现的代码。因此,它被限制成一个单一的继承。通过与接口联合使用,这一方案避免了对类似于C++虚拟基础类那样的一些机制的需要。

为创建可进行“例示”(即创建一个实例)的一个interface(接口)的版本,需使用implements关键字。它的语法类似于继承的语法,如下所示:

1046页程序

(34) Java中没有virtual关键字,因为所有非static方法都肯定会用到动态绑定。在Java中,程序员不必自行决定是否使用动态绑定。C++之所以采用了virtual,是由于我们对性能进行调整的时候,可通过将其省略,从而获得执行效率的少量提升(或者换句话说:“如果不用,就没必要为它付出代价”)。virtual经常会造成一定程度的混淆,而且获得令人不快的结果。final关键字为性能的调整规定了一些范围——它向编译器指出这种方法不能被取代,所以它的范围可能被静态约束(而且成为嵌入状态,所以使用C++非virtual调用的等价方式)。这些优化工作是由编译器完成的。

(35) Java不提供多重继承机制(MI),至少不象C++那样做。与protected类似,MI表面上是一个很不错的主意,但只有真正面对一个特定的设计问题时,才知道自己需要它。由于Java使用的是“单根”分级结构,所以只有在极少的场合才需要用到MI。interface关键字会帮助我们自动完成多个接口的合并工作。

(36) 运行期的类型标识功能与C++极为相似。例如,为获得与句柄X有关的信息,可使用下述代码:

X.getClass().getName();

为进行一个“类型安全”的紧缩造型,可使用:

derived d = (derived)base;

这与旧式风格的C造型是一样的。编译器会自动调用动态造型机制,不要求使用额外的语法。尽管它并不象C++的“new casts”那样具有易于定位造型的优点,但Java会检查使用情况,并丢弃那些“异常”,所以它不会象C++那样允许坏造型的存在。

(37) Java采取了不同的异常控制机制,因为此时已经不存在构建器。可添加一个finally从句,强制执行特定的语句,以便进行必要的清除工作。Java中的所有异常都是从基础类Throwable里继承而来的,所以可确保我们得到的是一个通用接口。

1047页程序

(38) Java的异常规范比C++的出色得多。丢弃一个错误的异常后,不是象C++那样在运行期间调用一个函数,Java异常规范是在编译期间检查并执行的。除此以外,被取代的方法必须遵守那一方法的基础类版本的异常规范:它们可丢弃指定的异常或者从那些异常衍生出来的其他异常。这样一来,我们最终得到的是更为“健壮”的异常控制代码。

(39) Java具有方法过载的能力,但不允许运算符过载。String类不能用+和+=运算符连接不同的字串,而且String表达式使用自动的类型转换,但那是一种特殊的内建情况。

(40) 通过事先的约定,C++中经常出现的const问题在Java里已得到了控制。我们只能传递指向对象的句柄,本地副本永远不会为我们自动生成。若希望使用类似C++按值传递那样的技术,可调用clone(),生成自变量的一个本地副本(尽管clone()的设计依然尚显粗糙——参见第12章)。根本不存在被自动调用的副本构建器。为创建一个编译期的常数值,可象下面这样编码:

static final int SIZE = 255

static final int BSIZE = 8 * SIZE

(41) 由于安全方面的原因,“应用程序”的编程与“程序片”的编程之间存在着显著的差异。一个最明显的问题是程序片不允许我们进行磁盘的写操作,因为这样做会造成从远程站点下载的、不明来历的程序可能胡乱改写我们的磁盘。随着Java 1.1对数字签名技术的引用,这一情况已有所改观。根据数字签名,我们可确切知道一个程序片的全部作者,并验证他们是否已获得授权。Java 1.2会进一步增强程序片的能力。

(42) 由于Java在某些场合可能显得限制太多,所以有时不愿用它执行象直接访问硬件这样的重要任务。Java解决这个问题的方案是“固有方法”,允许我们调用由其他语言写成的函数(目前只支持C和C++)。这样一来,我们就肯定能够解决与平台有关的问题(采用一种不可移植的形式,但那些代码随后会被隔离起来)。程序片不能调用固有方法,只有应用程序才可以。

(43) Java提供对注释文档的内建支持,所以源码文件也可以包含它们自己的文档。通过一个单独的程序,这些文档信息可以提取出来,并重新格式化成HTML。这无疑是文档管理及应用的极大进步。

(44) Java包含了一些标准库,用于完成特定的任务。C++则依靠一些非标准的、由其他厂商提供的库。这些任务包括(或不久就要包括):

■连网

■数据库连接(通过JDBC)

■多线程

■分布式对象(通过RMI和CORBA)

■压缩

■商贸

由于这些库简单易用,而且非常标准,所以能极大加快应用程序的开发速度。

(45) Java 1.1包含了Java Beans标准,后者可创建在可视编程环境中使用的组件。由于遵守同样的标准,所以可视组件能够在所有厂商的开发环境中使用。由于我们并不依赖一家厂商的方案进行可视组件的设计,所以组件的选择余地会加大,并可提高组件的效能。除此之外,Java Beans的设计非常简单,便于程序员理解;而那些由不同的厂商开发的专用组件框架则要求进行更深入的学习。

(46) 若访问Java句柄失败,就会丢弃一次异常。这种丢弃测试并不一定要正好在使用一个句柄之前进行。根据Java的设计规范,只是说异常必须以某种形式丢弃。许多C++运行期系统也能丢弃那些由于指针错误造成的异常。

(47) Java通常显得更为健壮,为此采取的手段如下:

■对象句柄初始化成null(一个关键字)

■句柄肯定会得到检查,并在出错时丢弃异常

■所有数组访问都会得到检查,及时发现边界违例情况

■自动垃圾收集,防止出现内存漏洞

■明确、“傻瓜式”的异常控制机制

■为多线程提供了简单的语言支持

■对网络程序片进行字节码校验

相关推荐

    java/c++区别

    3) **两者共有的特性**:Java和C++都是面向对象的,都支持继承、封装和多态,但Java的实现更简单,C++的多继承则更灵活。 (六) 详细介绍 在详细对比中,Java的类库和API更为丰富,C++的模板和预处理器则提供了更大...

    Java语言与C++语言的对比分析.pdf

    C++语言的数据类型繁多,从简单的整型、字符型到复杂的浮点型和逻辑型,每种数据类型还能进一步细分为双精度、单精度等具体形式。指针类型数据在C++中非常常见,通过指针变量能够直接操作内存地址。 C++语言的应用...

    The diffenences bwtween Java and C++ (JAVA与C++区别)

    本文旨在对比C++与Java这两种重要的计算机编程语言的特点。从复杂度、语法差异、内存管理等多个方面进行对比分析。 #### 关键词 C++;Java;差异 #### 引言 C++是一种广泛应用的计算机编程语言,它支持静态数据...

    《C++ for Java Programmers》高清完整英文PDF版

    书中的章节涵盖C++哲学、最简单的C++、指针和引用变量、基于对象的编程:类、运算符重载、面向对象的编程:继承、模板、异常控制流、输入和输出、集合:标准模板库、原始数组和字符串、C风格C++以及使用Java和C++:...

    C++,java,Go等语言性能对比

    ### C++, Java, Go 等语言性能对比分析 #### 概述 本文档由 Google 工程师 Robert Hundt 编写,旨在通过一种经验报告的形式,对 C++、Java、Go 和 Scala 四种编程语言进行性能比较。本研究关注于不同语言在容器类...

    经典算法java和C++实现

    "经典算法java和C++实现"这个资源集合了排序算法和走迷宫等基本算法的Java和C++实现,为学习者提供了一个宝贵的实践平台。下面我们将深入探讨这些算法及其在两种语言中的实现方式。 1. **排序算法**: - **冒泡...

    C++,C#,Java,Python实现简单的图形用户界面的区别和方法

    ### C++、C#、Java、Python 实现简单图形用户界面(GUI)的区别与方法 #### C++ 在C++中创建图形用户界面(GUI),主要依赖于Microsoft Foundation Classes(MFC)。MFC作为一套用于Windows应用程序开发的类库,...

    JAVA和C++区别详解

    ### JAVA和C++的主要区别详解 #### 一、运行机制与性能差异 1. **运行方式**: - **JAVA**是一种解释型语言,它的程序在运行时通过类加载器从类路径中加载相关的类,然后Java虚拟机(JVM)读取该类文件的字节码并...

    java和c++比较--虚函数和指针

    考虑一个简单的例子:两个类`Number`,分别在Java和C++中实现,具有相同的属性和方法。在Java中,由于引用的自动管理,当我们将一个`Number`对象赋值给另一个`Number`对象时,实际上只是复制了引用,指向同一个内存...

    java 与c++的比较

    ### Java与C++的比较分析 ...通过上述对比,我们可以看出Java和C++在设计哲学和技术特性上存在明显的差异。然而,无论是选择Java还是C++,最终的目标都是为了构建高效、可靠且易于维护的软件系统。

    Java与C++的比较

    ### Java与C++的比较 #### 一、引言 Java和C++是两种非常流行的计算机编程语言。...通过对比分析,我们可以看到Java和C++各有优势和适用场景,开发者可以根据具体的应用需求和技术偏好来选择最合适的编程语言。

    C++与java的综述与比较

    C++与Java都是面向对象的编程语言,Java从某种程度上来说是基于C++发展起来的,因此它们之间存在着诸多相似性和差异性。本文旨在对这两种语言进行一个全面的综述,并通过对比分析帮助读者更好地理解它们的特点以及...

    java于c++的区别

    - **并发模型**:Java内置了线程支持和高级并发API,如`ExecutorService`、`ForkJoinPool`等,使得多线程编程更加简单。C++虽然也有线程库支持,但在处理复杂的并发逻辑时相对复杂。 #### 结论 综上所述,Java和...

    java+OpenCV 图片对比、标记差异部分(可以支持中文路径)

    Java结合OpenCV库,能够有效地实现复杂的图像操作,比如图片对比和标记差异部分。本篇将深入探讨如何利用Java和OpenCV进行图片对比,并且支持中文路径。 首先,OpenCV是一个强大的开源计算机视觉库,它提供了丰富的...

    5、六种主流编程语言C++、PYTHON、JAVA对比.pdf

    C++、Python和Java是目前主流的编程语言,在软件开发领域中被广泛使用。它们各自有着不同的特点和适用场景。C++具有较强的性能和效率,适用于系统底层开发和游戏编程;Python则以其简洁性和强大的库支持著称,在数据...

    主流编程语言比较(C,C++,JAVA等。。)

    本文将对主流编程语言进行比较,包括 C、C++、Java 等语言,并对每种语言的特性、优点和缺点进行了详细的分析。 一、语言特性对比 | 语言 | 类型 | 静态/动态 | 支持面向过程 | 支持基于对象 | 支持范型 | 支持...

    NDK遍历sdcard简单实例(与java代码的速度对比)

    这个"NDK遍历sdcard简单实例"着重展示了如何利用NDK来遍历SD卡上的文件系统,并与Java代码进行速度对比,以体现原生代码的优势。 首先,我们要理解Android中的SD卡,即外部存储,通常用于存储用户数据和应用的大型...

    基于OpenCV+JAVA+C++的Android图像处理工具软件+源码+开发文档说明+实用教程(毕业设计&课程设计&项目开发)

    基于OpenCV+JAVA+C++的Android图像处理工具软件+源码+开发文档说明+实用教程,适合毕业设计、课程设计、项目开发。项目源码已经过严格测试,可以放心参考并在此基础上延申使用~ 基于OpenCV+JAVA+C++的Android图像...

    java web——人脸匹配

    Dlib则是一个C++库,但也有Java接口,其人脸识别模型非常准确。 实现人脸匹配通常分为以下步骤: 1. **图像预处理**:这一步包括灰度化、直方图均衡化、尺寸标准化等,以提高后续处理的效果。 2. **人脸检测**:...

    C#教程 讲得很详细 对比c++ 有助于有c++基础的人学习

    C#与C++和Java有着相似的语法,但简化了类、命名空间、方法重载和异常处理等方面的复杂性,使得编程更加容易且出错率更低。对于有C++基础的读者来说,学习C#会相对轻松。 1. **C#语言特点** - **.NET框架**:C#是...

Global site tag (gtag.js) - Google Analytics