如何学习C++

我觉得任何一门编程语言的都可以遵循以下的步骤

学习基础语法

就像学习任何一门人类语言一样,不知道语言的单词和语法就无法把这门语言作为工具和别人进行交流。编程语言,尤其是高级编程语言,就是人类和计算机交流的语言。不管你说得像不像母语者,至少基础的交流规则还是要掌握的。

同时,语法的学习也是一个螺旋上升的过程。我在大一C++课上就学了C++的基础语法,现在还是要时不时会去翻《C++ Primer Plus》。毕竟还没有编译器能实现C++最新标准的全部特性,你怎么能说自己掌握了全部的语法呢。

对于完全的初学者来说,我建议从博客或者一些快速入门网站掌握类型、输入输出、分支、循环,OOP的类的声明、继承、重载、模板以及STL等内容。

以下推荐一个快速入门的网站——菜鸟教程:

菜鸟教程

诚然这个网站的快速教程不是完美的,但对于中文母语者快速掌握一门编程语言的基础语法是绝对够用的了。

至于学到哪种程度比较好,我认为是能够用这个语言完成一项大学软件课设级别的项目就可以了,譬如说:图书管理系统、贪吃蛇、停车场预约系统等。

当然这只是满足基础使用的最小要求,接下来就是语法的大部头《C++ Primer Plus》了。在大多数情况下我都是把这本书当字典用的,哪里不会查哪里。但我非常建议刚入门的时候跟着目录粗读一遍全文,说是粗读,我估计也会花掉大几十个小时的时间。若是手敲代码,耗时会更长。我估计你大概率只能看懂30%或更少,但今后debug的时候,这些依稀残留在脑海中的记忆会帮你大忙。

另外在写代码参照C/C++标准库的时候,人手必备:

cppreference.com

网站有中文版,但是没有英文的全。

最后我认为在深入学习一门语法的时候,最重要的是和其他语言进行比较(如果C++是你的第一门编程语言,当我没说)以及知道这门语言的局限性。C++至今仍有不少生命力,肯定不光是历史包袱,别的语言的所做不到的事情也是他至今依然会以“如何学习xxx”的形式出现的原因之一。

理解了边界所在,才能掌握一门技术。因为只有知道了某个技术不能做到什么,你才能更好地做到所能做到的。

——《Thinking in Java》第十五章

学习最佳实践

我认为一门语言的最佳实践有两层含义:

一种是是无数程序员在编程中踩了无数坑之后总结出的经验教训;另一种是对于了解自己的编程过程中“对话的对象”,进而写出高效且优雅的代码。

何为“对话的对象”,即为承载你程序的主体,对于C++就是计算机或者Linux系统、对于Java就是JVM。

最佳实践的书,对于Java有《Effective Java》《深入理解Java虚拟机》等;对于C/C++有《Effective C++》、《C Trap and Pitfalls》、《深入C++对象模型等》等和Linux的各种书。

根据我的观察,读最佳实践相关的书可能会出现字不进脑袋的症状。并且最佳实践的知识在国内粗暴地退化为面试环节中的八股文,死记硬背让不少同学深恶痛绝。因人而异,我个人是很喜欢看相关书籍的。

另外,我认为Coding Style也可以作为语言最佳实践的一部分。Coding Style包括:

  • 变量、函数、文件、工程的命名
  • 工程目录的结构
  • 各种空格,大括号
  • 注释
  • etc

在会社或者团队中编程,你的代码需要被同事、上司Code Review,这时候代码就增加了一部分社会属性。就像你在公司和别人交流要学着如何礼貌和高效一样,代码的最佳实践帮助你更好地通过代码和同事一起工作。

Coding Style的参考书推荐《Google C++ Style Guide》。

写到这里我突然想到一个小故事。我今年在面试某家美资互联网的时候,OA阶段我答得一团糟,两道题都没有全部AC,和我一起投递的小伙伴们都是完美AC。最后发面试的时候,我竟然拿到了。后来问了问前辈,说是因为我代码写得很工整,每个空格、大括号都出现在它该出现的地方。

工程实践

这一步学习这门语言在工程中是如何运用的。如果是Java,大家大概会说去学Spring全家桶。而C++用法各异,对于不同的应用有着完全不同的工具栈。最后共通的工具可能就只有GDB和Makefile/CMake了。

在这一步,自己写几个小项目也是很好的提升编码能力的做法,以下我抛砖引玉几个:

JSON解析器

参考:

cJSON: Ultralightweight JSON parser in ANSI C

其中只有cJSON.c和cJSON.h是主要的程序

HTTP Server

用C用socket实现一个HTTP server算是最经典的

参考:

Tinyhttpd

这个项目只用了500行左右的C代码实现了一个静态HTTP服务器

自己实现STL

自己实现一个类STL的轮子有助于对各种语法细节和模板的理解,强力推荐

参考:

MyTinySTL

Web Framework

参考:

Oatpp

阅读开源项目代码

如何成为一个更好的开发者?很多人对这个问题的答案都会是阅读知名开源项目的代码。

阅读开源代码会提升编码品味、

但就我个人的经验来说,阅读大规模的源码是极其痛苦的过程(尽管他们一般都有着详细的注释)。看到几万几十万行的代码甚至连从哪里开始看都不知道,心里只剩绝望。

这里,我把我并不那么丰富的源码阅读经验总结分享给大家:

找最初始的版本开始读

比如你听说Nginx是一个优秀的开源项目,你在GitHub上搜到它,clone到本地,用vscode打开看了一眼目录结构,然后就没有然后了……

这些成熟的开源项目经过了很长时间的迭代,已经是一个很复杂的软件产品了。当它们刚出来的时候,没那么有名气,没那么稳定,没那么复杂,能实现基本的功能就行。早期版本,就是你很好的一个切入点了。我记得之前看SQLite最早期的版本也只有大几千行而已。

轮子库是一个很好的开始

工具类开源库库的一大特点就是各个组件之间非常地独立,整体的规模可能非常大,但单看一个模块的话,是一个可以接受的大小。

absl@Google

folly@Facebook