首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >用 C++ 和 Java 写算法,有差别吗?

用 C++ 和 Java 写算法,有差别吗?

作者头像
CSDN技术头条
发布于 2019-11-19 07:11:39
发布于 2019-11-19 07:11:39
2.6K0
举报
文章被收录于专栏:CSDN技术头条CSDN技术头条

我写了七、八年的 “算法博客”,出版了一本《算法的乐趣》,一门《算法应该怎么“玩”?》课程,所有介绍算法的例子都是用 C++ 编写的。

很多读者来向我吐槽:“好好的一本算法书,为什么要用 C++?” 或者 “C++ 很强大,Java 也很优秀,我选 Python”。

所以在本文里,我非常详细的讲述了用 Java 或 C++ 写算法时候的优劣势,你可以参考一下来判断自己喜欢用哪种语言写算法

PS: 下文中,上面的代码是 C++ 的实现方式,下面的是 Java 的实现方式。 C++ 语法使用的是 C++11之后的版本,Java 使用的是 Java6 之后的版本。

1、C++ 和 Java 语法特性的相似性

同为 C 语言家族的 Java 和 C++ 语言层面的相似性是有客观基础的。我通常这样理解:Java 是跨平台的 C++,是一种更好的 C++(是不是有点拉仇恨的感觉)。

2、基本数据类型

C++ 的基本数据类型有:int、unsigned int、long、unsigned long、short、unsigned short、char、unsigned char、bool、float 和 double;

相应的,Java 也有 8 种基本数据类型,分别是:byte、short、int、long、float、double、char 和 boolean。

大部分情况下,两种语言的基本数据类型可以根据下表进行一对一的转换,但是也有差异,需要特别注意。

首先是 char,C++ 的 char 是 8 比特无符号整数,顺便表示了 ASCII 字符;Java 的 char 是 16 比特,天生就可以表示宽字符集的字符。

另一个需要注意的是 long 类型,C++ 的 long 是不可移植类型,在不同的系统上其长度不一样,可能是 32 位,也可能是 64 位,所以 C++ 程序员应尽量避免使用 long。

Java 的 long 比较单纯,无论是 32 位的系统还是 64 位的系统,它都表示 64 位整数。

反过来,Java 会用 d 或 D 表示一个直接数字是 double 类型的浮点数,比如 200.0d 或(200.0D),但是 C++ 不支持,因为 C++ 默认一个浮点型的直接数字就是 double 类型。

C++ 用字面量符号 f 或 F 表示一个直接数字是 float 类型浮点数,比如 250.1 f(或 250.1F),这一点 Java 也是一样的。

C++ 用字面量符号 l 或 L 表示 long,用 UL 表示 unsigned long。

3、字符串

很多 C++ 程序员喜欢的用 char* 或 char 类型的数组存储字符串,这其实是 C 语言用户带过来的习惯,我给出的 C++ 算法实现对字符串一般都用 std::string,对应 Java 的 String。

std::stringString 的用法对照如下表所示:

4、基本语法

虽然 Java 的语法和 C++ 十分地相似,但是语言层面还有一些不同。C++ 允许全局函数的存在,Java 则不允许,不过 Java 也留了个口子,就是用静态成员函数。Java 没有指针,对象的传递和返回都是用的引用的方式,并且不需要像 C++ 那样用 “&” 做特殊的语法标记。

大多数介绍 Java 的书籍开篇就是类和抽象,然后才是基本的语法,这和 Java 上等人的气质是一致的,连这都不会,咋做程序员?C++ 应该多提升一下气质,少用点指针和全局函数。本文为了对比 C++ 和 Java 的相似性,所以就从基本语法结构开始介绍。

运算符和赋值

二者的运算符几乎一样,甚至 “++” 和 “—” 运算符都一样有前缀式和后缀式两种形式,意义也一样;运算符的优先级规则也是一样的。赋值语句两者基本上是一样的,看看每一行结尾的 “;” 你就知道它们有多相似。

条件判断与循环

条件判断方面,C++ 与 Java 的 if 语句、switch 语句用法都相同;逻辑表达式的结构和语法、逻辑运算符的优先级也都相同。

C++ 的三种基本循环方式是 while 循环、do…while 循环和 for 循环,Java 都支持,甚至连关键字和 break、continue 控制语句的意义也一样。

C++11 版本引入了一种根据范围循环的语法,一般理解和 Java 的增强 for 循环类似,比如这种 C++ 循环形式:

Java 与之对应的形式是:

C++ 的基于范围的 for 循环也可用于 C++ 的标准库对象,用于取代老旧的迭代器循环方式:

同样,Java 的增强 for 循环也支持基于 Collection 的遍历,理解起来不成问题:

传统的 C++ 语言是用迭代器对标准库的容器进行遍历,比如:

C++ 的容器都有 begin()end() 接口,分别得到起始位置的迭代器的值和结束位置的迭代器的值,很多标准库的算法都会用到迭代器。

C++ 用当前迭代器的值是否等于 end() 代表的结束位置迭代器的值来判断是否遍历结束。

Java 的 Collection 也有迭代器的机制,Java 用 hasNext() 判断是否遍历结束。

C++ 直接用 “ * ” 提领迭代器,得到对象本身的引用,Java 用迭代器的 next() 接口得到对象本身的引用。以上 C++ 代码可以翻译成如下 Java 代码:

除了以上的 for 循环语句,C++ 还支持 for_each() 形式的遍历 + 处理操作,也是配合迭代器使用,for_each() 的前两个参数是一对迭代器,代表循环的起始位置和结束位置。

第三个参数是一个可调用对象,即函数对象(C++11 版本之后,这个参数还可以是一个 Lambda 表达式),举个栗子:

Java 没有与之对应的泛型函数接口,但是 Java 的很多 Collection 都支持 forEach() 接口:

C++ 的 for_each()其实用起来并不好用,自从 C++11 之后,除了怀旧派 C++ 程序员,其他人应该很少会再用 for_each() 了,基于范围的 for 循环简直丝滑的不要不要的。

5、函数

C++ 的函数结构和 Java 也一样,函数调用的形参和实参对应方式也一样,也无需多做说明。

6、数组

C++ 和 Java 都支持原生数组,并且数组索引都是从 0 开始。C++ 中定义数组的同时就分配了存储空间,所以在定义时要指定长度,使用 new 动态申请内存时,要指定长度。

但是一种情况除外,那就是静态初始化数组的形式,因为此时编译器知道需要多少空间存储这些数据,如下是 C++ 定义数组的常用形式:

Java 如果仅仅是声明一个数组,可以不指定长度,因为此时并不分配存储空间,需要分配空间的时候,用 new。与之对应的 Java 语言的形式是:

C++ 中二维数组的每一维长度必须相同,因为 C++ 的二维数组实际上只是一块连续的存储空间而已,甚至可以用一维数组的下标遍历全部二维数组的存储空间。

Java 没这要求,因为 Java 的每一维都是可以单独申请存储空间的。但是二者在使用形式上是一样的。C++ 定义和初始化二维数组一般有这几种形式:

与之对应的 Java 语言初始化二维数组的形式是:

C++ 也支持动态内存形式的二维数组,一般有两种使用方法,Java 都有与之对应的习惯用法:

与之对应的 Java 的方法是:

这代码相似度很高。C++ 代码最后要用 delete[] 手动释放为数组申请的内存,Java 是不需要的。

C++ 还可以利用二维数组在内存中是连续存储这一特性,使用时用下标计算将一维数组当成二维数组使用,计算的方法是:a\[i]\[j] = b[i * 2 + j],如下代码示例:

遇到这样的代码,需要根据上述对应关系,小心地理解算法代码的意图。一些棋盘类游戏通常喜欢用一维数组存储二维的逻辑棋盘结构,好在 Java 也可以这么做,转换起来也没什么难度。

7、枚举

与 C 相比,C++ 强化了类型差异,枚举变量和整数变量之间不能互相赋值,但是使用方法依然是直接使用枚举值,没有限制域。

C++11 之后,开始支持强类型枚举,这一点就和 Java 很像了,越来越像一家人了:

8、I/O 系统

C++ 代码中一般用 std::cinstd::cout 进行控制台的输入和输出。也有一些半吊子 C++ 程序员会在 C++ 代码中混用 C 语言的 printf() 打印输出信息。

不过话说回来,很多语言都支持 printf 方式的格式化输出,比如 Java、 Python,为啥 C++ 就不能提供一个呢?比如以下代码接受用户输入一个字符串和一个整数,并将其输出出来:

将其翻译成 Java,是这个样子的:

上述代码示例中,C++ 和 Java 的输入分隔符都是空格或回车,如果希望输入带空格的一整行内容怎么办?

C++ 提供了 getline() 函数,getline() 会从缓冲区中取输入流,直到遇到结束符。

结束符默认是 '\n',实际上是 getline() 函数有三个参数,第三个参数可指定结束符:

Java 也有与之对应的 Buffer IO 方式,请看:

C++ 程序员有时候也会用 std::cin::get() 函数,这个函数也是从缓冲区中读入一行,直到遇到结束符,和 getline() 函数一样,这个函数也可以指定结束符,如果不指定,默认是'\n'

但是 std::cin::get() 函数有个小个性,就是它不从缓冲区中读出结束符,而是将结束符留在缓冲区中。

为了适应它的这个小个性,C++ 程序员通常会在后面跟一个 get,将结束符读出并丢弃掉,所以代码看起来有点怪怪的:

理解了这一点,看懂 C++ 代码也就不难了。当然,无论是 C++ 还是 Java,其 I/O 系统都非常复杂,有流式 I/O,也有缓冲区 I/O,操作的数据可以是控制台 I/O,也可以是文件 I/O。

9、类和封装

首先说说 C++ 的 struct,Java 没有与之对应的相似物的,但是完全可以用 class 来替换这个概念。为什么这么说呢?

因为在 C++ 中,struct 的位置有点尴尬,它是个 POD 吧,但它的成员又可以用非 POD 的数据类型,比如 std::string,甚至还可以定义虚接口,一旦有了这些东西,它就算不上 POD 了,除了成员默认是公有之外,和 class 没有太大差别。

在我看来,C++ 保留 struct 的主要意义是为了兼容旧的 C 或 C++ 的库,这些库中很多接口用到了 struct,其次是纯粹作为一种 POD 的 value type 来使用。

我的算法代码中也会用到 struct,大概是为了怀旧吧,其实完全可以用 class 代替,当然也可以很容易地翻译成 Java 的 class。来看个例子,对于这个 struct:

可以很轻松的转成 class:

自从 C++11 发布以后,我就觉得 C++ 和 Java 的 class 越来越像了,分开这么多年后,C++ 终于也支持 final 和 override 了。

从语法层面看,二者的差异很小,就小规模的算法而言,也很少会用到继承和重载之类的情况,所以,Java 程序员看懂 C++ 的 class 定义与实现一点都不难。

少有的一些差异,比如 C++ 的函数可以设置参数默认值,或者 C++ 的抽象机制采用的虚函数要使用 virtual 关键字等。先看一个典型的 C++ 类的定义与实现:

C++ 的类成员访问控制采用分节控制,用 public:protected: 作为分节的标志,如果没有分节标志的类成员,则是默认的 private: 控制。

C++ 的成员函数可以有默认值,并且构造函数也支持默认值。以 Bucket 类为例,构造函数第二个参数默认值是 0,即在构造 Bucket 对象时,可以只确定一个参数 capicity,也可以在确定 capicity 参数的同时,确定 Bucket 的水量,比如:

Java 不支持参数默认值,但是可以通过重载函数解决这个问题,即增加一个只有 capicity 参数的构造函数:

C++ 没有抽象基类的语法,但是又抽象基类的概念,一般当一个类中有一个纯虚函数的时候,这个类是不能被直接实例化的,它就类似于是一个抽象基类,比如:

C++ 的函数有很多类型修饰,比如常见的 const,C++11 后新增了 final 和 override,但是 = 0 一直是一个比较奇怪的存在,它表明这个函数没有实现,需要在派生类中实现,同时,也说明这个类是不能被实例化的。

对于这样的机制,Java 可以理解为这就是个抽象基类:

C++ 的继承体系的语法与 Java 类似,只是语法形式上不同,Java 采用关键字:extends

C++ 对于基类声明的虚函数,继承类中不需要再用 virtual 关键字修饰,当然,加了 virtual 关键字也没错误。Java 也一样,abstract 关键字再继承类中可以省去。

从 Shape 抽象类派生一个 Circle 类,C++ 的典型代码是:

Circle 构造函数后面的 :Shape(color),表示对基类的初始化,对于 Java 语言来说,相当于调用 super(color)

以上代码翻译成 Java 语言,应该是这样的形式:

C++ 有时候也会将一个类声明为 final,意味着它不希望被其他类继承,从语法上做了限制,比如:

有时候,是某个不希望被派生类重载,比如:

这些对于 Java 程序员来说,并不陌生,语法上只是 final 关键字的位置不同,理解上应该不存在任何问题。

10、总结

本文介绍了 C++ 和 Java 在基本语法层面的对应关系,因为算法代码涉及的语言方面深度有限,所以本文介绍的内容也比较基础。

通过对比发现不管是用 C++ 还是用 Java 来写算法,差别基本不大,如果朋友们对算法想再深度了解,可以看一下《算法应该怎么“玩”?》

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2018-11-21,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 GitChat精品课 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
C++教程(凯格尔训练法教程)
七种基本的C++数据类型:bool、char、int、float、double、void、wchar_t 类型修饰符:signed、unsigned、short、long 注:一些基本类型可以使用一个或多个类型修饰符进行修饰,比如:signed short int简写为short、signed long int 简写为long。
全栈程序员站长
2022/08/01
3.1K0
C++教程(凯格尔训练法教程)
算法刷题小技巧总结
数组过大超过限制,可定义为全局变量。开一个20000大小的数组,用memset函数赋初值。
天道Vax的时间宝藏
2021/08/11
5470
每个C++开发者都应该学习和使用的C++11特性
Hi,大家好!本文讨论了所有开发人员都应该学习和使用的一系列 C++11特性。该语言和标准库中有很多新增功能,本文只是触及了皮毛。但是,我相信其中一些新功能应该成为所有C++开发人员的日常工作。
Linux兵工厂
2024/03/21
2780
每个C++开发者都应该学习和使用的C++11特性
【C++】【期末考】【基本概念和语法】概括总结——期末速成
C++是一种面向对象的编程语言,由Bjarne Stroustrup在20世纪80年代初开发。它是在C语言的基础上增加了面向对象的特性,从而既具有C语言的高效性,又提供了高级的编程抽象。C++已经成为许多系统级软件、游戏、嵌入式系统以及高性能计算应用程序的主要编程语言。
小李很执着
2024/06/17
2720
【C++】【期末考】【基本概念和语法】概括总结——期末速成
【C++强基篇】学习C++就看这篇--->STL之string使用及实现
STL(standard template libaray-标准模板库):是C++标准库的重要组成部分,不仅是一个可复用的组件库,而且是一个包罗数据结构与算法的软件框架
HABuo
2025/07/15
1370
【C++强基篇】学习C++就看这篇--->STL之string使用及实现
8.1 C++ STL 变易拷贝算法
C++ STL中的变易算法(Modifying Algorithms)是指那些能够修改容器内容的算法,主要用于修改容器中的数据,例如插入、删除、替换等操作。这些算法同样定义在头文件 <algorithm> 中,它们允许在容器之间进行元素的复制、拷贝、移动等操作,从而可以方便地对容器进行修改和重组。
王 瑞
2023/08/16
3580
C++的输入输出特点、运算符重载及标准模板库STL
程序的输入都建有一个缓冲区,即输入缓冲区。一次输入过程是这样的,当一次键盘输入结束时会将输入的数据存入输入缓冲区,而cin函数直接从输入缓冲区中取数据。正因为cin函数是直接从缓冲区取数据的,所以有时候当缓冲区中有残留数据时,cin函数会直接取得这些残留数据而不会请求键盘输入。 注意:cin>>和cin.get()都残留数据不会出错,但是cin.getline会报错,下面的示例中都有体现。
Here_SDUT
2022/06/29
9040
C++的输入输出特点、运算符重载及标准模板库STL
C++ 宇宙穿越指南:小白从新手村到编程巅峰的奇幻之旅
这篇万字长文专为 C++ 小白打造。从 C++ 历史、应用领域讲起,详述学习环境搭建。由基础数据类型、控制流程,深入到类、模板等特性。搭配实践项目,给出学习方法与常见问题解法,助力小白全面掌握 C++,实现编程能力的飞跃 。
羑悻的小杀马特.
2025/03/21
3430
C++ 的发展
C++ 是由 Bjarne Stroustrup 于 1979 年在贝尔实验室(Bell Labs)开始开发的,最初是作为 C 语言的一个扩展,目的是在不丧失 C 语言高效性的基础上,提供面向对象编程的特性。C++ 的发展历程可以分为以下几个重要阶段:
ljw695
2024/11/15
1.1K0
C++ 的发展
【C++之STL】一文学会使用 string
STL(standard template libaray-标准模板库):是C++标准库的重要组成部分,不仅是一个可复用的组件库,而且是一个包罗数据结构与算法的软件框架。
fhvyxyci
2024/11/11
2960
【C++之STL】一文学会使用 string
c++ 11 新特性
赖勇浩(http://laiyonghao.com) 声明:本文源自 Danny Kalev 在 2011 年 6 月 21 日发表的《The Biggest Changes in C++11(and Why You Should Care)》一文,几乎所有内容都搬了过来,但不是全文照译,有困惑之处,请参详原文(http://www.softwarequalityconnection.com/2011/06/the-biggest-changes-in-c11-and-why-you-should-care/ )。 注:作者 Danny Kalev 曾是 C++ 标准委员会成员。
bear_fish
2018/09/20
1K0
C++数据结构之——数组
数组是一种线性数据结构,用于存储一组具有相同类型的数据元素。其基本特性包括:固定大小、顺序存储、随机访问。C++中支持多层数组的实现,能够满足复杂场景的需求。
红目香薰
2025/02/07
3880
C++查缺补漏
本文总结了几乎所有不易理解或是容易忘记的C++知识,可作为手册查阅,内容参考自清华大学郑莉教授的C++课程。
luxuantao
2021/02/20
2.7K0
C++入门基础知识
C++是一种通用的、面向对象的编程语言,由Bjarne Stroustrup于1985年在贝尔实验室开发。它是C语言的扩展,增加了面向对象编程的特性。
用户11720881
2025/06/27
1440
今天你学C++了吗?——string(上)
早期 C/C++ 中 auto 的含义是:使用 auto 修饰的变量,是具有自动存储器的局部变量 。使用auto替换长类型就十分方便~
用户11352420
2025/03/02
1270
今天你学C++了吗?——string(上)
【C++】string类的基本使用
下面这篇文章写的非常不错,十分推荐大家看看。(我的建议是搞懂UTF-8的编码规则即可,UTF-16和32不常用,所以掌握UTF-8的编码原理就足够了,因为这些知识只要了解即可,知道有这么回事就行,不必过于细究。)
举杯邀明月
2023/04/12
5950
【C++】string类的基本使用
C++11新特性学习笔记
C++11标准为C++编程语言的第三个官方标准,正式名叫ISO/IEC 14882:2011 - Information technology – Programming languages – C++。在正式标准发布前,原名C++0x。它将取代C++标准第二版ISO/IEC 14882:2003 - Programming languages – C++成为C++语言新标准。
CtrlX
2023/03/13
2.4K0
C++11新特性学习笔记
C++ 中的 `string` 类型:全面解析与高效操作
在 C++ 中,string 类型是对字符数组的高级封装,它提供了大量内置函数,使得字符串的处理变得更为简便和高效。与 C 风格的字符数组不同,string 类型不仅自动管理内存,还提供了更丰富的操作方法。本文将通过详细讲解 string 类型的概念、常见操作及相关函数,帮助你快速掌握这一强大工具。
平凡之路.
2025/02/06
3680
C++ 中的 `string` 类型:全面解析与高效操作
C/C++ 中带空格字符串输入的一些小trick
上面这段代码并不能很好的统计字符串中每个英文字母在其中的出现频率,我苦思冥想了许久,才发现了一个曾经忽略过的一个问题,cin 标准输入字符串在遇到空格时候将会被截断,而我们需要对输入一个带空格的字符串进行特殊处理,而使用 getline 可以完美的解决该问题。getline(std::cin, std::string) 在输入回车符号时才会被截断,把上述代码的输入做一些调整就可以完美的解决问题。
Angel_Kitty
2019/10/06
3.1K0
一文让你学完C++,干货收藏!!!
C++ 是一种静态类型的、编译式的、通用的、大小写敏感的、不规则的编程语言,支持过程化编程、面向对象编程和泛型编程。
小林C语言
2020/04/03
3.3K0
相关推荐
C++教程(凯格尔训练法教程)
更多 >
交个朋友
加入腾讯云技术交流站
洞悉AI新动向 Get大咖技术交流群
加入云原生工作实战群
云原生落地实践 技术难题攻坚探讨
加入前端学习入门群
前端基础系统教学 经验分享避坑指南
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档