前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >如果一定要在 C++ 和 Java 中选择,是选 C++ 还是 Java ?

如果一定要在 C++ 和 Java 中选择,是选 C++ 还是 Java ?

作者头像
范蠡
发布2022-02-12 10:09:55
4.2K0
发布2022-02-12 10:09:55
举报
文章被收录于专栏:高性能服务器开发

一、我的经历

说说我的经历,在 C++ 和 Java 之间我经历了这么几个阶段:

  1. 大学浅尝辄止地学过一段时间 Java,后来放弃开始学 C/C++;
  2. 本科毕业到硕士学的都是 C++;
  3. 工作以后非 C++ 开发不做,先做 C++ 客户端开发,再转 C++ 服务器开发;
  4. 后来机遇巧合去了携程旅行网做 Java 开发;
  5. 前年离开携程,与人合伙创业,做技术负责人,大部分核心系统用 Java 开发,只有其中一个系统用 C++ 开发;
  6. 离开创业团队,拿到了阿里的 P7 offer(Java 开发岗位,未去)
  7. 拿了饿了么 C++ 开发岗位的 offer(做公司定制的数据研发),也未去。
  8. 目前在某独角兽公司写 Go。

二、选 C++ 还是选 Java?

作为过来人,我的建议是:

如果你是学生或有大把空余时间,那建议你把 C++ 学好,C++ 被称为程序员的九阳神功是有一定的道理的,并不是说 C++ 有多难学,而是 C++ 技术栈的学习讲究的是其背后的一系列操作系统原理,你把 C++ 学好了,就意味着你把这些背后的原理学好了,你之后再学其他任何语言和机制都轻松很多;

如果你急着找工作,或者对编程没多大兴趣,只是为了糊口饭吃,那么你可以优先选 Java,甚至 Java 的八股文面经背一背,如果运气不错的话,也能找到一份不错的工作。

三、C++ 该怎么学?

C/C++ 这门语言与其他高级语言不同,它是离操作系统较近的语言。所以学好 C/C++ 体系的技术栈必须结合操作系统的运行机制来学习,通俗地说,就是你必须掌握操作系统层面的几大基础知识,他们是汇编、编译链接与运行时体系、狭义的操作系统原理、多线程、网络编程,只有这样学习,你才能学的懂、学的通透、学以致用。咱们学习 C++ 不是为了理论研究,而是付诸实践,投入生产是吧。

用一张图来概括一下 C++ 技术栈吧:

3.1 学好 C++ 语言包括 C++11/14/17 常用语法

C++ 面试关于语法部分一般会问以下一些问题,当然这些问题也是 C++ 开发必备:

  • 在有继承关系的父子类中,构建和析构一个子类对象时,父子构造函数和析构函数的执行顺序分别是怎样的?
  • 在有继承关系的类体系中,父类的构造函数和析构函数一定要申明为 virtual 吗?如果不申明为 virtual 会怎样?
  • 什么是 C++ 多态?C++ 多态的实现原理是什么?
  • 什么是虚函数?虚函数的实现原理是什么?
  • 什么是虚表?虚表的内存结构布局如何?虚表的第一项(或第二项)是什么?
  • 菱形继承(类 D 同时继承 B 和 C,B 和 C 又继承自 A)体系下,虚表在各个类中的布局如何?如果类B和类C同时有一个成员变了 m,m 如何在 D 对象的内存地址上分布的?是否会相互覆盖?

部分同学对以上问题总是搞不清楚,但是又不知道如何学习,于是从网上找各种文章来学习,造成这块的知识非常零碎,无法构成体系,其实这与其在网上花费大量时间,不如系统地看一下侯捷老师翻译的《深度探索 C++ 对象模型》一书。 这本书专注于 C++ 面向对象程序设计的底层机制,包括结构式语意、临时性对象的生成、封装、继承,以及虚拟——虚拟函数和虚拟继承。这本书让你知道:一旦你能够了解底层实现模型,你的程序代码将获得多么大的效率。对于 C++ 底层机制感兴趣的读者,这是一本让你大呼过瘾的绝妙好书。

另外,时至今日,各大企业虽然项目中未必用到 C++11/14/17 常用的语言特性和类库,但是面试还是对这些有一定的要求的,常问的有:

  • 统一的类成员初始化语法与 std::initializer_list<T>
  • 注解标签(attributes)
  • final/override/=default/=delete 语法
  • auto 关键字
  • Range-based 循环语法
  • 结构化绑定
  • stl 容器新增的实用方法
  • std::thread
  • 线程局部存储 thread_local
  • 线程同步原语 std::mutex、std::condition_variable 等
  • 原子操作类
  • 智能指针类
  • std::bind/std::function

C++11/14 网上的资料已经很多了,C++17 的资料不多,重头戏还是 C++11 引入的各种实用特性,这就给读者推荐一些我读过的不错的书籍:

  • 《深入理解 C++11:C++11 新特性解析与应用》
  • 《深入应用 C++11:代码优化与工程级应用》
  • 《C++17 完全指南》
  • 《Cpp 17 in Detail》

3.2 进一步提高 C++

当你学习好了 C++ 语言本身,你可以学习一下 C++ 的一些常见惯用法和高性能编码实践,这里我推荐一本经典书籍叫《提高 C++ 性能的编程技术》,这本书详细讨论了临时对象、内存管理、继承、虚函数、内联、引用计数以及 stl 等一切有可能提升 C++ 效率的细节内容。最终,该书将c++性能提升的各种终极利器,完美地呈现在读者的面前!最关键的是,这本书非常薄,但是书中介绍的每个专题都是实战中常用的技术,强烈推荐。

3.3 C++ 工程实践

在掌握了 C++ 常用语法和语言背后的实现机制和常用惯用法后,我强烈推荐另外两本书,一本是 《C++ API 设计》 和《大规模 C++ 程序设计》,前者从细粒度地教你在实际开发中如何设计 C++ API 接口,后者告诉你大型 C++ 程序小到单个 .h/cpp 文件如何编写,大到大型 C++ 项目如何组织的最佳实践。这两本书都是工程实践的图书,书中的技术可以实实在在地用于一线开发。

3.4 与 C/C++ 相关的必知必会知识

第一个基础知识是汇编

我们学习汇编不是一定要用汇编来写代码,就像我们学习 C/C++ 也不一定单纯为了面试和找工作。

对于 C/C++ 的同学来说,汇编是建议一定要掌握的,只有这样,你才能在书写 C++ 代码的时候,清楚地知道你的每一行C++代码背后对应着什么样的机器指令,if/for/while 等基本程序结构如何实现的,函数的返回值如何返回的,为什么整型变量的数学运算不是原子的,最终你知道如何书写代码才能做到效率最高。掌握了汇编,你可以明白,在 C++ 中,一个栈对象从构造到析构,其整个生命周期里,开发者的代码、编译器和操作系统分别做了什么。

掌握了汇编,你可以理解函数调用是如何实现的,你可以理解函数的几种调用方法,为什么printf这样的函数其调用方式不能是 __stdcall,而必须是 __cdecl。掌握了汇编,你就能明白为什么一个类对象增加一个方法不会增加其实际占的内存空间。推荐的书籍是王爽老师的《汇编(第三版)》 和韩宏老师的《老码识途 从机器码到框架的系统观逆向修炼之路》 。

第二个基础知识是编译、链接与运行时体系知识

作为一个开发者,要清楚地知道我们写的 C/C++ 程序是如何通过预处理、编译与链接等步骤最终变成可执行的二进制文件,操作系统如何识别一个文件为可执行文件,一个可执行文件包含什么内容,执行时如何加载到进程的地址空间,程序的每一个变量和数据位于进程地址空间的什么位置,如何引用到。一个进程的地址空间有些什么内容,各段地址分布着什么内容,为什么读写空指针或者野指针会有内存问题。一个进程如何装在各个 so 或 dll 文件的,这些文件被加载到进程地址空间的什么位置,如何被执行,数据如何被交换。

第三个基础知识是狭义的操作系统原理。这里加上“狭义”二字是因为从广义上来讲,以上所说的内容都是操作系统原理的范畴。狭义的操作系统原理这里包括操作系统如何管理进程与线程,虚拟内存与物理内存之间的对应关系,何为内存映射文件,进程之间如何通信等等。

这两者推荐的书单:《程序员的自我修养》和 《Windows 核心编程》,尤其是《程序员的自我修养》,搞 C++ 开发不看此书,读尽 C++ 语言书也枉然!

第四个基础知识是多线程知识

严格来说,这点已经包括在第三点之中了,我之所以将其单独列出来,是因为多线程编程是我们做应用服务最常用的技术之一。最近面试过几个学历非常好的同学,对于一个进程中如果某个线程因为内存问题而退出,是否会导致整个进程退出的问题答不好,实在不应该。多线程知识其实不难学,立足于理解与实践而不是应付面试,可以学的很好。无论是 Windows 还是 Linux 操作系统,操作系统提供的线程同步对象就那么几种,Windows 常用的有临界区(关键端)、Event、互斥体、信号量等,Linux 有互斥体、信号量、读写锁、条件变量,这些知识点学过则会,不学则不会。这些线程同步原语花上几天就能搞得清楚,大多数同学不是学不会,而是不愿意学,但是偏偏喜欢在简历上写上自己熟悉多线程编程。面试的时候,被问到条件变量的虚假唤醒机制都说不清楚,非要说自己用过条件变量。这是一些同学犯的很低级的错误,如果真用过条件变量,如果不知道虚假唤醒机制,那一定写的代码是不对的。市场上目前没有任何一本图书对以上知识形成体系的介绍,当然,我的本书填补了这一空缺,你将从本书中获得从进程与线程的关系,再到常用的线程同步原语的区别与使用场景,再到线程池以及基于生产者消费者模型的消息队列,以及对协程思想介绍的相关知识。

掌握了常见的多线程同步原语之后,接下来可以找一些带多线程的项目去学习一下,不管是否带 UI 的都行。我推荐的一种方式是,使用 gdb 或者 Visual Studio 调试器将你需要学习的多线程程序中断下来,在多线程面板,看看这个进程一共有多少个正在运行的线程,分析每个线程的作用,然后研究下这些线程在何时何地创建的,为什么需要创建新的线程。尝试爱过几个人,面对爱情你会诚实很多;尝试研究几个多线程项目,面对多线程你会熟练许多。

推荐的书单 《C++ 服务器开发精髓》。

第五个是网络编程,直白地说就是 Socket 编程。操作系统层面提供的 API 会在相当长的时间内保持接口不变,一旦学成,终生受用。理解和掌握常用的基础 socket API 不仅可以最大化地去定制各种网络通信框架,更不用说使用市面上流行的网络通信库了,最重要的是,它会是你排查各种网络疑难杂症坚实的技术保障。操作系统层面提供的网络模型就那么几种,无论像 Java/Go/Python 等语言如何封装,作为技术的源头,我们有什么理由不去掌握它呢?推荐的书单 《TCP/IP 网络编程》和《Linux 高性能服务器编程》 。

以上是基于 C++ 技术栈来说,并没有包括算法与数据结构、数据库等方面的基本功。总而言之,学习 C++ 不能只盯着 C++ 语法本身,还要熟悉 C++ 技术栈背后的一系列操作系统原理。

3.5 C/C++ 如何练习

光纯粹通过看书,可能学习效果不一定好,你一定要装一个 C/C++ 语言开发工具实际去写一写 C/C++ 代码,

Windows 上我推荐学习 Visual Studio 编译、调试和运行 C/C++ 代码,以下是一些步骤:

Visual Studio 2019 启动画面

新建一个工程

创建一个控制台程序

给控制台程序起一个名字

如果学习C语言,可以将 .cpp 文件扩展名改成 .c

编译项目

添加程序断点

启动调试

学会在“监视窗口”查看运行过程中的变量名

学会在“堆栈窗口”查看程序调用堆栈

学会在“内存窗口”查看程序变量的内存值

调试状态下,需要熟悉的一些窗口

如果你不想只用 C 语言写一些黑洞洞的命令行程序,可以看一下《Windows 程序设计(第五版)》这本书,这本书从零教你如何编写 Windows 界面程序:

这本书是一本经典的 Windows 编程圣经,曾经伴随着近 50 万 Windows 程序员步入编程殿堂,成长为 IT 时代的技术精英,可以这么说,中国常用的 QQ、360 安全卫士的开发者都是靠这本书启蒙的。

如果你在 Linux 下使用 C 语言编写服务程序,要学会 gcc、Makefile、CMake 等工具,推荐一下《GNU Make 手册》:

链接: https://pan.baidu.com/s/11NZs2IPi8sMZu4n8LRgttA 提取码: hcj6

和《CMake 最佳实践》这两本书:

链接: https://pan.baidu.com/s/1flVSq6bwu0n-Y7vXheVpkw 提取码: 44ta

编译好程序之后,你可以使用 GDB 进行调试,GDB 掌握常用命令即可,这个很容易学,实际上手操作一下,几分钟就学会了,GDB 常用命令:

GDB 常用命令

学习 GDB 推荐《Debugging with GDB》一书:

链接: https://pan.baidu.com/s/1e3toHeLoQrnEr1KS7Rhn7g 提取码: h0d3

3.6 推荐一些不错的 C++ 开源项目

如何阅读开源项目可以看这里:

张小方:如何去阅读并学习一些优秀的开源框架的源码?

如何调试开源 C/C++ 项目的代码可以看这里:

张小方:如何高效的学习 Nginx 源码,汲取养分?

3.6.1 Filezilla

2016 年的时候,我无意中发现我用了多年的 FTP 软件 Filezilla 竟然用 C++ 11 重写了。

Filezilla界面

FileZilla 的源码是一个德国开发者写的,其代码质量也不错,而且使用的是 C++11 写的。可以一边调试一边学习,学完后,我的 C++11 功能得到了大大增强。

不怕你笑话,我在上学的时候,曾看过 Filezilla 0.x 版本的代码,那个时候 UI 界面用的还是 MFC。

贴一下 Filezilla 的部分代码,红框标出来的部分为 C++11 的语法特性:

代码质量总体很不错。我修改了下让其可以在 Visual Studio 中调试,这样你可以一边调试一边学习。

一套源码如果能够容易编译、调试,同时其业务是容易理解的(通俗地说,就是这套代码的功能是什么的),那么才利于新手学习。

我已经将环境和依赖都配置好了,代码获取方式:

打开关注后回复“获取Filezilla源码”得到下载链接

3.6.2. uWebSocket

uWebSocket 是一款开源的 WebSocket 库,最新版使用了大量 C++17 的语法,代码量非常少。

下载地址:https://github.com/uNetworking/uWebSockets

我们改造了这个项目,用于我们的交易系统的行情推送服务器。

3.6.3 TeamTalk

TeamTalk 是蘑菇街开源的一款用于企业内部的即时通信工具,其代码下载地址是:

https://github.com/balloonwj/TeamTalk

3.6.4. poco 库

POCO C++ Libraries - Simplify C++ Development poco 库是一个代码质量非常高,且文档比较丰富的 C++ 库,实现了常用的一些功能,可以根据自己的喜好挨个看。

https://pocoproject.org/

3.6.5. FlamingIM

https://github.com/balloonwj/flamingo

我为 Flamingo 专门录制了 3 部高清技术讲解视频以方便读者学习,视频中介绍了 Flamingo 的编译和部署方法、整体架构、各个模块的技术实现细节以及如何学习Flamingo的方法,需要视频教程下载链接

链接: https://pan.baidu.com/s/1p_dBPJqgsvpLXvVyCotjUg 提取码: ah6c

3.6.6. tinySTL

https://github.com/balloonwj/TinySTL

学好 C/C++ 并非一朝一夕之功,需要不断坚持加努力,一旦学成,奇妙无穷,加油!!

四、Java 该怎么学?

4.1 Java 基础知识

Java 的基础知识包括如下部分:

1. 基础语法部分
01、Java 基础语法与运行/编译环境
  • JRE/JDK
  • Java 变量和字面值
  • Java 数据类型
  • Java 操作符
  • Java 输入输出
  • Java 表达式 & 语句 & 代码块
  • Java 注释
02、Java 流程控制
  • Java if else
  • Java switch 语句
  • Java for 循环
  • Java while 循环
  • Java break 语句
  • Java continue 语句
03、Java 数组
  • Java 数组
  • 多维数组
  • Java 数组复制
04、Java 面向对象
  • Java 类和对象
  • Java 方法
  • Java 方法重载
  • Java 构造方法
  • Java 字符串
  • Java 访问权限
  • Java this 关键字
  • Java final 关键字
  • Java 递归
  • Java instanceof 操作符
  • Java 继承
  • Java 方法重写
  • Java super 关键字
  • 抽象类 & 抽象方法
  • Java 接口
  • Java 多态
  • Java 封装
  • 嵌套&内部类
  • Java static 关键字
  • Java 匿名内部类
  • Java 单例
  • Java 枚举类
  • Java 枚举构造方法
  • Java 枚举字符串
  • Java 反射
05、Java 异常处理
  • Java 异常简介
  • Java 异常处理
  • Java try catch
  • Java throw 和 throws
  • Java 捕获多个异常
  • Java try-with-resources
  • Java 注解
  • Java 注解类型
  • Java 日志
  • Java 断言
06、Java 集合与队列
  • Java 集合框架
  • Java 集合接口
  • Java List 接口
  • Java ArrayList
  • Java Vector
  • Java Stack
  • Java 队列接口
  • Java 优先级队列
  • Java 双端队列接口
  • Java LinkedList
  • Java 数组队列
  • Java 阻塞队列接口
  • Java ArrayBlockingQueue
  • Java LinkedBlockingQueue
  • Java Map 接口
  • Java HashMap
  • Java LinkedHashMap
  • Java WeakHashMap
  • Java EnumMap
  • Java SortedMap 接口
  • Java NavigableMap 接口
  • Java TreeMap
  • Java ConcurrentMap 接口
  • Java ConcurrentHashMap
  • Java Set 接口
  • Java HashSet
  • Java EnumSet
  • Java LinkedHashSet
  • Java SortedSet 接口
  • Java NavigableSet 接口
  • Java TreeSet
  • Java 集合算法
  • Java 迭代器接口
  • Java ListIterator 接口
07、Java I/O
  • Java InputStream
  • Java OutputStream
  • Java FileInputStream
  • Java FileOutputStream
  • Java ByteArrayInputStream
  • Java ByteArrayOutputStream
  • Java ObjectInputStream
  • Java ObjectOutputStream
  • Java BufferedInputStream
  • Java BufferedOutputStream
  • Java PrintStream
  • Java Reader
  • Java Writer
  • Java InputStreamReader
  • Java OutputStreamWriter
  • Java FileReader
  • Java FileWriter
  • Java BufferedReader
  • Java BufferedWriter
  • Java StringWriter
  • Java PrintWriter

学习 Java 基础知识推荐以下两本书:

  • Java核心技术卷1 基础知识
  • Java核心技术卷2高级特性

有人提到《Thinking In Java》这本书,那就说一下这本书,这个书出版的年代比较久远了,加上 JDK 已经更新换代很多年了,各种新的特性和接口被加进来,这本书中部分内容已经过时了,加上这本书比较厚,如果时间不是很充足,不建议使用这本书学习。

4.2. Java 并发编程(多线程)

  • 进程与线程的区别
  • 多线程的入门类和接口
  • 线程组和线程优先级
  • 线程的状态及主要转化方法
  • 线程间的通信
  • 重排序和 happens-before
  • volatile
  • synchronized 与锁
  • CAS 与原子操作
  • AQS
  • 计划任务
  • Stream 并行计算原理
  • Fork/Join
  • 通信工具类
  • CopyOnWrite
  • 并发集合容器
  • 锁接口和类
  • 阻塞队列
  • 线程池原理

Java 并发编程首推《Java并发编程实战》:

另外《Java并发编程的艺术》这一本也不错。

4.3. Java 网络编程

  • 《Java网络编程》
  • 《Java网络编程精解》

4.4 Java 虚拟机

无论是 Java 面试还是想成为 Java 高手或者在一些项目中进行性能调优都必须掌握的知识,一般需要掌握以下内容:

  • Java 内存结构
  • 垃圾回收
  • JVM 内存区域
  • Java 虚拟机栈
  • class 文件
  • 字节码指令
  • JVM 参数调优
  • Java 对象模型
  • HotSpot
  • 类加载机制
  • 编译和反编译
  • 反编译工具(javap)
  • JIT
  • 虚拟机性能监控和故障处理工具(jps、jstack、jmap、jstat、jconsole、javap)

推荐的书是《深入理解Java虚拟机》,周志明老师的这本书现在已成了 Java 虚拟机中的经典的经典,建议从事 Java 开发的同学一定要好好看一看。

另外,《揭秘Java虚拟机——JVM设计原理与实现》这本书也不错。

4.5. Java Web

  • 深入分析Java Web技术内幕 修订版

4.6 Java 框架

4.6.1. Netty

搞 Java 的如果不熟悉 Netty 框架,那很难成为高手,虽然我们平常开发基本不会直接用到 netty,但是各种框架底层基本上都用的是 Netty,学习 Netty 可以分两步走:

  • 第一步,学会如何使用 Netty,推荐《Netty In Action》(中译名:《Netty 实战》),或者看《Netty 权威指南》,这本书也很不错。
  • 第二步,深入研究 Netty 的源码,学习源码中各种技术,netty 的官方源码地址:https://github.com/netty/netty
4.6.2. SSM 框架

现在 Java 的主流开发基本使用 SSM 框架,所谓 SSM 框架指的是 Spring + Spring MVC + MyBatis。关于 SSM 的书,其实没有特别好的,可以自己搭个框架,边看边调试,或者结合一些网络实例视频来学习。推荐

  • Spring面试题知识点合集(https://www.bilibili.com/video/BV1t44y1C73F/
  • SSM 实战 100 集(https://www.bilibili.com/video/BV1NX4y1G7wx

五、注重基础的学习

需要注意的是,无论学 C++ 还是 Java,想要在技术之路走的远,一定不要疏忽数据结构算法、操作系统原理、计算机网络、设计模式、数据库等基础知识的学习。

原创不易,如果觉得有用,请给 @张小方 点个赞吧。

你好,我是张小方,畅销书《C++服务器开发精髓》作者,多年 C/C++/Java/Golang 开发经验,大厂技术专家、面试官,擅长客户端和高性能高并发服务开发。

我创作了专辑《C++高级进阶》《后端开发面试题》《多线程重难点解析》《网络编程重难点解析》《网络通信协议深度解析》《服务器开发进阶》《面试、offer 与薪资那些事儿》《职业规划》《张小方的故事》。

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

本文分享自 高性能服务器开发 微信公众号,前往查看

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、我的经历
  • 二、选 C++ 还是选 Java?
  • 三、C++ 该怎么学?
    • 3.1 学好 C++ 语言包括 C++11/14/17 常用语法
      • 3.2 进一步提高 C++
        • 3.3 C++ 工程实践
          • 3.4 与 C/C++ 相关的必知必会知识
            • 3.5 C/C++ 如何练习
              • 3.6 推荐一些不错的 C++ 开源项目
                • 3.6.1 Filezilla
                • 3.6.3 TeamTalk
                • 3.6.4. poco 库
                • 3.6.5. FlamingIM
                • 3.6.6. tinySTL
            • 四、Java 该怎么学?
              • 4.1 Java 基础知识
                • 1. 基础语法部分
              • 4.2. Java 并发编程(多线程)
                • 4.3. Java 网络编程
                  • 4.4 Java 虚拟机
                    • 4.5. Java Web
                      • 4.6 Java 框架
                        • 4.6.1. Netty
                        • 4.6.2. SSM 框架
                    • 五、注重基础的学习
                    相关产品与服务
                    云服务器
                    云服务器(Cloud Virtual Machine,CVM)提供安全可靠的弹性计算服务。 您可以实时扩展或缩减计算资源,适应变化的业务需求,并只需按实际使用的资源计费。使用 CVM 可以极大降低您的软硬件采购成本,简化 IT 运维工作。
                    领券
                    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档