# 【NO.584】C++这么难，为什么我们还要学习C++？

**前言**

C++ 可算是一种声名在外的编程语言了。这个名声有好有坏，从好的方面讲，C++ 性能非常好，哪个编程语言性能好的话，总忍不住要跟 C++ 来单挑一下；从坏的方面讲，它是臭名昭著的复杂、难学、难用。当然，这样一来，熟练的 C++ 程序员也就自然而然获得了 “水平很高” 的名声，所以这也不完全是件坏事。

不管说 C++ 是好还是坏，不可否认的是，C++ 仍然是一门非常流行且非常具有活力的语言。继沉寂了十多年，并终于发布语言标准的第二版 —— C++11，再那之后，C++ 以每三年一版的频度发布着新的语言标准，每一版都在基本保留向后兼容性的同时，提供着改进和新功能。

## 1. 为什么难学

每次提到 C++ 编程，无论你是使用 C++ 的开发者，还是使用其他编程语言和开发环境的开发者，我们对 C++ 的评价往往都是 “复杂且难学”。为什么 C++ 会留下这样的口碑？追根溯源，主要有两个原因。

第一个原因是 C++ 的包容性，即向前兼容。

C++ 类似 Objective-C，是 C 语言的超集，它希望尽量向下兼容 C 的一切语法和特性（在 C99 标准之前甚至是完全兼容），因此足够接近硬件底层。但这是把双刃剑。

虽然 C99 之前语法足够简单，但实际使用的复杂性并不低，而 C++ 为了兼容 C 语言的语法付出了很大的代价，并在此基础上设计并发展出了多范式的编程模型，这意味着可以继续采用面向过程的编程模式，也可以转向面向对象。与此同时，现代 C++ 还提供了一组函数式编程工具。

因此，在现代 C++ 得到发展以前，实际开发时到底要选用何种范式或者如何合理组合，一直让我们很头痛。

C++ 兼容 C 有什么代价呢？比如，C 的指针类型声明就备受 C++ 之父 Bjarne Stroustrup 诟病，但是为了向前兼容，不得不在这种声明模式下继续扩展。

第二个原因是 C++ 的设计哲学，“不为任何抽象付出不可接受的多余运行时性能损耗”。

纵观 C++40 多年的演进历程，可以发现每一次演进所支持的都是和编译时相关的新特性，而相对来说，运行时特性非常少，除了在面向对象的编程模型基础上提出的多态以外，几乎再无运行时特性（其他的均以库的形式提供）。这是因为 C++ 是零成本抽象，也就是说，开发者在使用 C++ 表达抽象概念时，无需忍受多余的运行时性能开销。

因此，虽然 C++ 具备很多高级抽象的语法特性，但在设计与具体使用过程中，我们仍然需要考虑各种各样的问题，包括基础对象内存模型、虚函数的设计、基于模板的泛型系统、基于模板的静态反射体系，以及到目前为止都是由编译器决定可选的垃圾回收（在其他现代语言中可以说是必备的特性了），这就让我们学习和使用 C++ 变得更复杂了。

![img](https://pic3.zhimg.com/80/v2-10092b7607b7b0f32ec0b656f4215292_720w.webp)

的确，这真够复杂的。一门编程语言必定有其局限性，这也是为什么 “更为现代” 的 Go 和 Rust 出现了，试图解决一些问题，特别是安全性方面。

不过作为语言的使用者，你肯定会问，那今后的 C++ 学习和使用会有哪些变化呢？这个问题，有人曾经问过 C++ 之父 Bjarne Stroustrup。

> 诸如 Go 和 Rust 编程语言新贵，它们在发力解决安全性和易用性方面的问题，规避缓冲区溢出这样的漏洞，甚至 Linux kernel 也开始考虑或采纳对 Rust 的支持，您是否觉得这会成为 C++ 的一个潜在的巨大威胁和挑战？

他的回答简单明了。

> “每隔几年，就会出现 C++ 的挑战者，我相信它们一定会有支持者。但是，C++ 的独特的语言特性、应用场景，以及 C++ 标准发展的方向，会让 C++ 继续茁壮成长。”

我特别喜欢这个回答。是啊，劣势固然存在，但 C++ 经过历史的检验，在高性能计算、低延迟处理、图形学领域以及机器学习等前沿技术领域有着难以替代的优势。

C++ 的 “复杂且难学” 一定程度上取决于向前兼容的能力和设计哲学，但正因如此，维护多年的系统仍然能与全新开发的系统友好地对接和集成，C++ 的包容性和多样性也让它极具发展力。

自 C++11 标准诞生以来，我们正式迈入现代 C++ 世界，而 C++20 及后续演进标准作为继 C++11 之后的又一次重大变革，给我们带来了新思想、新工具，让我们从容面对以往难以解决的问题。

## 2. C++的意义

C++ 程序员应该都听到过下面这种说法：

- C++ 是一门多范式的通用编程语言。

多范式，是因为 C++ 支持面向过程编程，也支持面向对象编程，也支持泛型编程，新版本还可以说是支持了函数式编程。同时，上面这些不同的范式，都可以在同一项目中组合使用，这就大大增加了开发的灵活性。因此，C++ 适用的领域非常广泛，小到嵌入式，大到分布式服务器，到处可以见到 C++ 的身影。

下面是一些著名的用到 C++ 的场合：

- 大型桌面应用程序（如 Adobe Photoshop、Google Chrome 和 Microsoft Office）
- 大型网站后台（如 Google 的搜索引擎）
- 游戏（如 StarCraft）和游戏引擎（如 Unreal 和 Unity）
- 编译器（如 LLVM/Clang 和 GCC）
- 解释器（如 Java 虚拟机和 V8 JavaScript 引擎）
- 实时控制（如战斗机的飞行控制和火星车的自动驾驶系统）
- 视觉和智能引擎（如 OpenCV、TensorFlow）
- 数据库（如 Microsoft SQL Server、MySQL 和 MongoDB）

有些同学可能会觉得，这些应用场景似乎和平时的开发场景有点远啊！你的感觉是对的。有些传统上使用 C++ 的场合现在已经不一定使用 C++，最典型的是个人电脑上的桌面应用。以前 Windows 下开发桌面应用常常用 MFC，微软的 C++ 框架。目前很流行的 Visual Studio Code 主要是用 TypeScript 写的，不是 C++。

C++ 的传统领域有被侵蚀的风险，那是因为和它相竞争的语言远远不止一个，可以说是上下夹攻。

- 如果专注性能和最小内存占用的话，C 仍然是首选——嵌入式领域用 C 非常多，而 Linux 也是用纯 C 写的。
- 如果专注抽象表达和可读性的话，那 Python 之类的脚本语言则要方便得多。
- 图形界面（GUI）编程传统上是 C++ 的地盘，但近年来 C# 和 JavaScript 占领了很大一部分市场。
- 游戏算是 C++ 的经典强项了，但有了 C++ 写的游戏引擎，游戏用 C# 写也没啥问题了——你可能不一定知道，Unity 游戏引擎上的首选开发语言是 C#，而王者荣耀是用什么游戏引擎呢？答案正是 Unity —— 所以王者荣耀可以认为是用 C# 开发的。
- 还有，Go 和 Rust 也加入了战团，对 C++ 形成了一定的竞争……

目前，跟 C++ 定位差不多、能有直接竞争关系的，也就是既支持高度抽象、又追求高性能的通用编程语言，其实只有 Rust 一种。而 Rust 远没有达到跟 C++ 一样的成熟和普及程度。这也可以从 TIOBE 的排名看出来：C++ 是第 4 位，而 Rust 是第 25 位。

另外，和 C 的兼容性，也是 C++ 的一大优势。虽然现在很多大型程序都混杂了多种语言，但在小项目里，减少语言的数量可以简化开发和部署。

## 3. 什么时候该用C++

C++ 既然性能又好，又支持抽象，为什么没有更流行呢？

C++ 比起 C 来，要更安全，更不容易出现缓冲区溢出这类漏洞，但跟没有指针概念的语言比起来，它仍然是一种“不安全”的语言。我的个人经验，完成同样的功能，C++ 需要的代码行数一般是 Python 的三倍左右，而性能则可以达到 Python 的十倍以上。

**那么问题来了：你在开发上额外付出的时间，能从性能上省回来吗？**

显然，这取决于你开发软件的用途和开发时间。举个例子，如果你用 Python 开发需要一天，运行需要十秒，并且不需要反复运行；那么，转用 C++ 开发就意味着开发费用也许要增加两倍，开发加运行的总时间增加两天，大亏。

反之，如果用 Python 开发还是需要一天，单次运行需要十秒，但是软件会作为服务长时间运行、每天被调用十万次。在这种情况下，明显你就需要多台服务器来支撑其使用了。这时，如果用 C++ 开发会需要额外的两天，但跟 Python 相比，部署上有望节约十分之九的硬件和电费 —— 那就很值了。

简言之，当你的软件属于运算密集或者内存密集型，你需要性能、且愿意为性能付出额外代价的时候，应该考虑用 C++，特别在你的代码需要部署在多台服务器或者移动设备的场合。反之，如果性能不会成为你开发的软件的瓶颈，那 C++ 可能就不是一个最合适的工具。

此外，在嵌入式应用的场景，那就根本不是值不值、而是行不行的问题。如果程序完成一个功能不能在指定的若干毫秒、甚至微秒内完成，那产品根本是失败、不可用的。在这种场合，能和 C++ 竞争的只有 C，但 C 是一种开发效率更低、更需要堆人力的语言了。在嵌入式开发使用 C++ 的最大障碍可能不是技术，而是人力资源——搞嵌入式开发的程序员可能大多都习惯使用纯 C 了。

由于 C++ 是解决性能问题的利器，短时间里在市场上没有真正的竞争对手，对 C++ 的需求会在相当长的时间里一直存在，尤其在大公司和像金融机构一样对性能渴求的地方。

> 顺便提一句，C++ 之父 Bjarne Stroustrup 目前就职的地方便是摩根斯坦利。

## 4. 如何学习C++

作为很多聪明人使用过的语言，C++ 在某些场合也可能被用来炫技，写出除了本人之外谁都看不懂的高抽象代码。这恰恰是 Bjarne 想努力抵制的方向。他想让 C++ 对初学者变得更为友好，也明确提出过，他不希望 C++ 是一种让人们耍机灵的语言，而是一种让人们更易于使用的语言。

学习 C++ 语言就像学一门活跃使用中的外语，你不要期望能够掌握所有的单词和语法规则 —— 那对于世界上 99.999999% 的人来说是不可能的。但语言是服务于人的，语法规则也是服务于人的，是为了让人们能够更好地沟通和表达。虽然 C++ 的每一个新标准都是让语言从定义和规则的角度变得更复杂，但从用法上来说，新标准允许人们能够更简单地表达自己的计算意图。跟学外语一样，我们需要的是多看多写，掌握合适的 “语感”，而不是记住所有的规则。

Bjarne 有一个洋葱理论： 抽象层次就像一个洋葱，是层层嵌套的。如果想用较低的抽象层次表达较高的概念，就好比一次切过了很多层洋葱，你会把自己的眼泪熏出来的。与这个思路相反，教 C++ 往往有一种不好的倾向，从那些琐碎易错的底层教起，自底向上，使得很多人常常在尚未领悟到抽象的真谛之前就已经被 C++ 的复杂性吓翻，从入门到放弃；或者，在学了基本的 C 语法和 class 之后就满足了，错过了高级抽象带来的全新境界。他主张学习应当自顶向下，先学习高层的抽象，再层层剥茧、丝丝入扣地一步步进入下层。如果一次走太深的话，挫折可能就难免了。

## 5.C++后端开发学习路线分享

最后，分享一个c/c++后端开发的学习知识图谱（摘自零声教育的大纲：对标腾讯T9职级技术栈，腾讯认证的）

**c++后端开发是一个庞杂的技术栈，因为没有统一的开发框架并且应用行业非常广泛。所有涉猎广泛，这里就把c/c++后端开发的技术点进行整理总结，看完以后，不会让你失望的。**

1. 精进基石
2. 高性能网络设计
3. 基础组建设计
4. 中间件开发
5. 开源框架
6. 云原生
7. 性能分析
8. 分布式架构
9. 上线实战

**1、精进基石，分为四个方面（数据结构，设计模式，c++新特性，Linux工程管理）**

数据结构部分

![img](https://pic4.zhimg.com/80/v2-a5e872e3f4ebff5f2e47f2839381a697_720w.webp)

设计模式

![img](https://pic3.zhimg.com/80/v2-03372ea2ce2feba7b108b66afeeb6e86_720w.webp)

C++新特性

![img](https://pic4.zhimg.com/80/v2-e50b7ad8735d347813040f9f90659aff_720w.webp)

linux工程管理

![img](https://pic4.zhimg.com/80/v2-176af3c57e8866f90356046dac8cc39f_720w.webp)



**2. 高性能网络设计（网络编程，网络原理，协程ntyco，用户态协议栈ntytcp）**

网络编程

![img](https://pic4.zhimg.com/80/v2-5426286b52a4957bc46d48b4b9768563_720w.webp)

网络原理

![img](https://pic3.zhimg.com/80/v2-30bacbf284fb94be950b8e3596d8d0aa_720w.webp)

自研框架： 纯c实现的协程（2000行代码）

![img](https://pic3.zhimg.com/80/v2-b6c40b94153b578adcb44fe354126bda_720w.webp)

自研tcp协议栈

![img](https://pic3.zhimg.com/80/v2-55103cd32fabf773893fe9e4ab525bd6_720w.webp)

高性能异步io机制io_uring

![img](https://pic2.zhimg.com/80/v2-b340e0b3ad0f7ceaab837839532e4f11_720w.webp)



**3. 基础组建设计，分为3部分， 池式组件，高性能组件，开源组件**

池式结构

![img](https://pic4.zhimg.com/80/v2-72e17934511f04b79d01387dd94b86af_720w.webp)

高性能组件

![img](https://pic1.zhimg.com/80/v2-21b403e920c42f632a0dee44c271c858_720w.webp)

开源组件

![img](https://pic4.zhimg.com/80/v2-449701cb30c276c67d2623835aa9c6bf_720w.webp)

4、中间件开发专栏

redis

![img](https://pic2.zhimg.com/80/v2-bbd008b47aaad5448750f93ceb95107d_720w.webp)

mysql

![img](https://pic2.zhimg.com/80/v2-411af5395fd23586dadb09a155430a45_720w.webp)

kafka

![img](https://pic3.zhimg.com/80/v2-fd1a3b402cdadbc1c9cfc56aa51f5ce6_720w.webp)

gRPC

![img](https://pic1.zhimg.com/80/v2-a2cea85a67a10a5e8563cf7cd0caef04_720w.webp)

nginx

![img](https://pic4.zhimg.com/80/v2-e8f9b4ca68300f7c797012869cfdfe2f_720w.webp)

**5. 开源框架**

游戏后端开源框架 skynet

![img](https://pic3.zhimg.com/80/v2-ef9162678cafae13eefb9bd94f85c53a_720w.webp)

分布式API网关

![img](https://pic1.zhimg.com/80/v2-70a66668b090577855763d4dbcac07a0_720w.webp)

DPDK

![img](https://pic1.zhimg.com/80/v2-16aa9606a881b6caf0b5765d571adfb0_720w.webp)

高性能计算CUDA

![img](https://pic2.zhimg.com/80/v2-19977aff14842f4756a6cb5d505f6f91_720w.webp)

**6、云原生专栏**

**docker**

![img](https://pic3.zhimg.com/80/v2-94e4caa56462fa1e22e31c92eb8137de_720w.webp)

kubernetes

![img](https://pic2.zhimg.com/80/v2-4f5ab6da7b798ebdde603942cab39481_720w.webp)

**7、性能分析专栏**

**性能与测试工具**

![img](https://pic3.zhimg.com/80/v2-021a78849d8efbf9e55e58e9581f4c6e_720w.webp)

观测技术bpf与ebpf

![img](https://pic3.zhimg.com/80/v2-16af55bef7b272f54e2a52f9f2983fda_720w.webp)

内核源码机制

![img](https://pic3.zhimg.com/80/v2-d7d1469ca1fc6e4bcf75247f47ab0842_720w.webp)



**8、分布式架构专栏**

**rocksdb**

![img](https://pic3.zhimg.com/80/v2-e6ce9f016c9bdf3aa775e593b43199fa_720w.webp)

TiDB

![img](https://pic4.zhimg.com/80/v2-cc8fddf5551aaa0b4aa5155ea529be5b_720w.webp)

分布式服务

![img](https://pic3.zhimg.com/80/v2-f22f724500b4f8e7b4d63bed73f92392_720w.webp)

**9、上线项目实战（可以写入简历的两个实战项目，让面试不再为没有项目发愁）**

**1、图床共享云存储**

**2、微服务即时通讯**

原文地址：https://zhuanlan.zhihu.com/p/608825768

作者：linux